Поскольку вы объявили награду, я поделюсь своими с трудом завоеванными секретами ...
В общем, все SQL-запросы, которые я настроил сегодня, требовали использования подзапросов. Я пришел из мира баз данных Oracle, и то, что я считал само собой разумеющимся, с MySQL не работало. И мое чтение о настройке MySQL заставляет меня сделать вывод, что MySQL отстает от Oracle в плане оптимизации запросов.
В то время как простые запросы, необходимые для большинства приложений B2C, могут хорошо работать для MySQL, большинство запросов агрегированного типа для отчетов, необходимых для Intelligence Reporting, похоже, требует изрядного планирования и реорганизации запросов SQL, чтобы MySQL мог их выполнять быстрее.
Администрация:
max_connections
количество одновременных подключений. Значение по умолчанию - 100 соединений (151 с версии 5.0) - очень мало.
Примечание:
соединения занимают память, и ваша ОС может не справиться с большим количеством соединений.
Двоичные файлы MySQL для Linux / x86 позволяют иметь до 4096 одновременных подключений, но самкомпилированные двоичные файлы часто имеют меньшие ограничения.
Установите table_cache в соответствии с количеством ваших открытых таблиц и одновременных подключений. Следите за значением open_tables, и если оно быстро растет, вам нужно будет увеличить его размер.
Примечание:
Для двух предыдущих параметров может потребоваться много открытых файлов. 20 + max_connections + table_cache * 2 - хорошая оценка того, что вам нужно. MySQL в Linux имеет параметр open_file_limit, установите этот предел.
Если у вас есть сложные запросы, вероятно, очень важны sort_buffer_size и tmp_table_size. Значения будут зависеть от сложности запроса и доступных ресурсов, но рекомендуемые начальные точки - 4 МБ и 32 МБ соответственно.
Примечание. Это значения «для каждого соединения», среди которых read_buffer_size, read_rnd_buffer_size и некоторые другие, что означает, что это значение может потребоваться для каждого соединения. Итак, при настройке этих параметров учитывайте вашу нагрузку и доступные ресурсы. Например, sort_buffer_size выделяется, только если MySQL необходимо выполнить сортировку. Примечание: будьте осторожны, чтобы не закончиться память.
Если у вас установлено много подключений (например, веб-сайт без постоянных подключений), вы можете повысить производительность, установив для thread_cache_size ненулевое значение. 16 - хорошее значение для начала. Увеличивайте значение, пока ваши thread_created не будут расти очень быстро.
ОСНОВНОЙ КЛЮЧ:
В таблице может быть только один столбец AUTO_INCREMENT, он должен быть проиндексирован и не может иметь значения DEFAULT.
KEY обычно является синонимом INDEX. Атрибут ключа PRIMARY KEY также может быть указан как просто KEY, если он указан в определении столбца. Это было реализовано для совместимости с другими системами баз данных.
ПЕРВИЧНЫЙ КЛЮЧ - это уникальный индекс, в котором все ключевые столбцы должны быть определены как NOT NULL.
Если индекс PRIMARY KEY или UNIQUE состоит только из одного столбца, имеющего целочисленный тип, вы также можете ссылаться на столбец как «_rowid» в операторах SELECT.
В MySQL имя ПЕРВИЧНОГО КЛЮЧА - PRIMARY.
В настоящее время только таблицы InnoDB (v5.1?) Поддерживают внешние ключи.
Обычно вы создаете все нужные вам индексы при создании таблиц. Любой столбец, объявленный как PRIMARY KEY, KEY, UNIQUE или INDEX, будет проиндексирован.
NULL означает «не имеет значения». Для проверки на NULL нельзя использовать операторы арифметического сравнения, такие как =, <или <>. Вместо этого используйте операторы IS NULL и IS NOT NULL:
NO_AUTO_VALUE_ON_ZERO подавляет автоматическое приращение для 0, так что только NULL генерирует следующий порядковый номер. Этот режим может быть полезен, если в столбце AUTO_INCREMENT таблицы был сохранен 0. (Кстати, хранение 0 не рекомендуется.)
Чтобы изменить значение счетчика AUTO_INCREMENT, которое будет использоваться для новых строк:
ALTER TABLE mytable AUTO_INCREMENT = value;
или SET INSERT_ID = значение;
Если не указано иное, значение будет начинаться с: 1000000 или указать его так:
...) ENGINE = MyISAM DEFAULT CHARSET = latin1 AUTO_INCREMENT = 1
ТАЙМЕРЫ:
Значения столбцов TIMESTAMP преобразуются из текущего часового пояса в UTC для хранения и из UTC в текущий часовой пояс для извлечения.
http://dev.mysql.com/doc/refman/5.1/en/timestamp.html
Для одного столбца TIMESTAMP в таблице вы можете назначить текущую метку времени в качестве значения по умолчанию и значения автообновления.
одна вещь, на которую следует обратить внимание при использовании одного из этих типов в предложении WHERE, лучше всего делать WHERE datecolumn = FROM_UNIXTIME (1057941242), а не WHERE UNIX_TIMESTAMP (datecolumn) = 1057941242. выполнение последнего не будет использовать индекс в этом столбце.
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
UNIX_TIMESTAMP()
FROM_UNIXTIME()
UTC_DATE()
UTC_TIME()
UTC_TIMESTAMP()
если вы конвертируете datetime в unix timestamp в MySQL:
А затем добавляете к нему 24 часа:
А затем конвертируете его обратно в datetime, он волшебным образом теряет час!
Вот что происходит. При преобразовании метки времени unix обратно в дату-время учитывается часовой пояс, и так получилось, что между 28 и 29 октября 2006 года мы перешли на летнее время и потеряли час.
Начиная с MySQL 4.1.3, функции CURRENT_TIMESTAMP (), CURRENT_TIME (), CURRENT_DATE () и FROM_UNIXTIME () возвращают значения в текущем часовом поясе соединения , который доступен как значение системной переменной time_zone. Кроме того, UNIX_TIMESTAMP () предполагает, что ее аргумент является значением даты и времени в текущем часовом поясе.
Текущая настройка часового пояса не влияет на значения, отображаемые такими функциями, как UTC_TIMESTAMP (), или значения в столбцах DATE, TIME или DATETIME.
ПРИМЕЧАНИЕ: ON UPDATE обновляет DateTime ТОЛЬКО при изменении поля. Если UPDATE не приводит к изменению полей, DateTime НЕ обновляется!
Кроме того, первый TIMESTAMP всегда по умолчанию AUTOUPDATE, даже если не указан
При работе с датами я почти всегда перехожу к юлианской дате, потому что математика данных - это простой вопрос добавления или вычитания целых чисел и секунд с полуночи по той же причине. Мне редко требуется временное восстановление с большей детализацией, чем секунды.
Оба они могут быть сохранены как 4-байтовое целое число, и если пространство действительно ограничено, их можно объединить во время UNIX (секунды с эпохи 1/1/1970) как целое число без знака, которое будет годным примерно до 2106 как:
секунд за 24 часа = 86400
'Целое число со знаком max val = 2147483647 - может содержать 68 лет секунд
'Целое число без знака max val = 4294967295 - может содержать 136 лет секунд
Бинарный протокол:
MySQL 4.1 представил двоичный протокол, который позволяет отправлять и возвращать значения нестроковых данных в собственном формате без преобразования в строковый формат и обратно. (Очень полезно)
Кроме того, mysql_real_query () быстрее, чем mysql_query (), потому что он не вызывает strlen () для работы со строкой оператора.
http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html
Бинарный протокол поддерживает подготовленные операторы на стороне сервера и позволяет передавать значения данных в собственном формате. Бинарный протокол претерпел значительные изменения в более ранних выпусках MySQL 4.1.
Вы можете использовать макрос IS_NUM (), чтобы проверить, имеет ли поле числовой тип. Передайте значение типа в IS_NUM (), и оно вернет значение ИСТИНА, если поле числовое:
Следует отметить, что двоичные данные МОГУТ быть отправлены внутри обычного запроса, если вы его избегаете и помните, что MySQL требует только экранирования обратной косой черты и символа кавычки. Так что это действительно простой способ ВСТАВИТЬ более короткие двоичные строки, например, зашифрованные / соленые пароли.
Главный сервер:
http://www.experts-exchange.com/Database/MySQL/Q_22967482.html
http://www.databasejournal.com/features/mysql/article.php/10897_3355201_2
ГРАНТ REPLICATION SLAVE ON . для slave_user ИДЕНТИФИЦИРОВАНО 'slave_password'
#Master Binary Logging Config STATEMENT causes replication
to be statement-based - default
log-bin=Mike
binlog-format=STATEMENT
server-id=1
max_binlog_size = 10M
expire_logs_days = 120
#Slave Config
master-host=master-hostname
master-user=slave-user
master-password=slave-password
server-id=2
Файл двоичного журнала должен читать:
http://dev.mysql.com/doc/refman/5.0/en/binary-log.html
http://www.mydigitallife.info/2007/10/06/how-to-read-mysql-binary-log-files-binlog-with-mysqlbinlog/
http://dev.mysql.com/doc/refman/5.1/en/mysqlbinlog.html
http://dev.mysql.com/doc/refman/5.0/en/binary-log.html
http://dev.mysql.com/doc/refman/5.1/en/binary-log-setting.html
Вы можете удалить все двоичные файлы журнала с помощью оператора RESET MASTER или их часть с помощью PURGE MASTER.
--result-file = binlog.txt TrustedFriend-bin.000030
Нормализация:
http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html
Функции UDF
http://www.koders.com/cpp/fid10666379322B54AD41AEB0E4100D87C8CDDF1D8C.aspx
http://souptonuts.sourceforge.net/readme_mysql.htm
Типы данных:
http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html
http://www.informit.com/articles/article.aspx?p=1238838&seqNum=2
http://bitfilm.net/2008/03/24/saving-bytes-efficient-data-storage-mysql-part-1/
Следует отметить, что в смешанной таблице с CHAR и VARCHAR mySQL изменит CHAR на VARCHAR
RecNum integer_type UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (RecNum)
MySQL всегда представляет даты с первым годом в соответствии со стандартными спецификациями SQL и ISO 8601.
Разное:
Отключение некоторых функций MySQl приведет к уменьшению размера файлов данных и более быстрому доступу. Например:
--datadir укажет каталог данных и
--skip-innodb отключит опцию inno и сэкономит вам 10-20 миллионов
Подробнее здесь
http://dev.mysql.com/tech-resources/articles/mysql-c-api.html
Скачать Глава 7 - Бесплатно
InnoDB является транзакционным, но с ним связаны накладные расходы на производительность. Я обнаружил, что таблиц MyISAM достаточно для 90% моих проектов. Таблицы, не являющиеся безопасными для транзакций (MyISAM), имеют несколько собственных преимуществ, и все они возникают по следующим причинам:
нет накладных расходов на транзакцию:
Намного быстрее
Меньшие требования к дисковому пространству
Для выполнения обновлений требуется меньше памяти
Каждая таблица MyISAM хранится на диске в трех файлах. Файлы имеют имена, начинающиеся с имени таблицы, и расширение, указывающее тип файла. В файле .frm хранится формат таблицы. Файл данных имеет расширение .MYD (MYData). Индексный файл имеет расширение .MYI (MYIndex).
Эти файлы могут быть скопированы в место хранения в неизменном виде без использования функции резервного копирования администраторов MySQL, которая требует много времени (как и восстановление).
Уловка состоит в том, чтобы сделать копию этих файлов и затем УДАЛИТЬ таблицу. Когда вы поместите файлы обратно, MySQl распознает их и обновит таблицу отслеживания.
Если вам необходимо выполнить резервное копирование / восстановление,
Восстановление резервной копии или импорт из существующего файла дампа может занять много времени в зависимости от количества индексов и первичных ключей, имеющихся в каждой таблице. Вы можете значительно ускорить этот процесс, изменив исходный файл дампа, добавив к нему следующее:
SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;
.. your dump file ..
SET FOREIGN_KEY_CHECKS = 1;
COMMIT;
SET AUTOCOMMIT = 1;
Чтобы значительно увеличить скорость перезагрузки, добавьте команду SQL SET AUTOCOMMIT = 0; в начале файла дампа и добавьте COMMIT; команду до конца.
По умолчанию автоматическая фиксация включена, что означает, что каждая команда вставки в файле дампа будет обрабатываться как отдельная транзакция и записываться на диск перед запуском следующей. Если вы не добавите эти команды, перезагрузка большой базы данных в InnoDB может занять много часов ...
Максимальный размер строки в таблице MySQL составляет 65 535 байт.
Эффективная максимальная длина VARCHAR в MySQL 5.0.3 и on = максимальный размер строки (65 535 байт)
Значения VARCHAR не дополняются при сохранении. Конечные пробелы сохраняются при сохранении и извлечении значений в соответствии со стандартным SQL.
Значения CHAR и VARCHAR в MySQL сравниваются без учета конечных пробелов.
Использование CHAR ускорит ваш доступ, только если вся запись имеет фиксированный размер. То есть, если вы используете какой-либо объект переменного размера, вы можете сделать все из них переменного размера. Вы не получите скорости, используя CHAR в таблице, которая также содержит VARCHAR.
Предел VARCHAR в 255 символов был увеличен до 65535 символов в MySQL 5.0.3.
Полнотекстовый поиск поддерживается только для таблиц MyISAM.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
Столбцы BLOB не имеют набора символов, а сортировка и сравнение основаны на числовых значениях байтов в значениях столбцов.
Если строгий режим SQL не включен, и вы назначаете значение столбцу BLOB или TEXT, превышающее максимальную длину столбца, значение усекается, чтобы соответствовать размерам, и генерируется предупреждение.
Полезные команды:
проверьте строгий режим: SELECT @@ global.sql_mode;
выключить строгий режим:
НАБОР @@ global.sql_mode = '';
НАБОР @@ global.sql_mode = 'MYSQL40'
или удалите: sql-mode = "STRICT_TRANS_TABLES, ...
ПОКАЗАТЬ КОЛОННЫ ОТ mytable
ВЫБРАТЬ max (namecount) AS virtualcolumn
FROM mytable ORDER BY virtualcolumn
http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-fields.html
http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_last-insert-id
last_insert_id ()
получает вам PK последней строки, вставленной в текущий поток max (pkcolname) дает вам последний PK в целом.
Примечание: если таблица пуста, max (pkcolname) возвращает 1 mysql_insert_id () преобразует тип возвращаемого значения встроенной функции MySQL C API mysql_insert_id () в тип long (названный int в PHP).
Если ваш столбец AUTO_INCREMENT имеет тип столбца BIGINT, значение, возвращаемое mysql_insert_id (), будет неправильным. Вместо этого используйте внутреннюю функцию MySQL SQL LAST_INSERT_ID () в запросе SQL.
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
Обратите внимание, что когда вы пытаетесь вставить данные в таблицу и получаете сообщение об ошибке:
Unknown column ‘the first bit of data what you want to put into the table‘ in ‘field list’
используя что-то вроде
INSERT INTO table (this, that) VALUES ($this, $that)
это потому, что у вас нет апострофов вокруг значений, которые вы пытаетесь вставить в таблицу. Поэтому вам следует изменить свой код на:
INSERT INTO table (this, that) VALUES ('$this', '$that')
напоминание, что `` используются для определения полей, баз данных или таблиц MySQL, а не значений;)
Потеряно соединение с сервером во время запроса:
http://dev.mysql.com/doc/refman/5.1/en/gone-away.html
http://dev.mysql.com/doc/refman/5.1/en/packet-too-large.html
http://dev.mysql.com/doc/refman/5.0/en/server-parameters.html
http://dev.mysql.com/doc/refman/5.1/en/show-variables.html
http://dev.mysql.com/doc/refman/5.1/en/option-files.html
http://dev.mysql.com/doc/refman/5.1/en/error-log.html
Настройка запросов
http://www.artfulsoftware.com/infotree/queries.php?&bw=1313
Что ж, этого должно быть достаточно, чтобы заработать бонус, я думаю ... Плоды многих часов и многих проектов с отличной бесплатной базой данных. Я разрабатываю серверы данных приложений на платформах Windows в основном с использованием MySQL. Худший беспорядок, который мне пришлось исправить, был
Абсолютный кошмар устаревшей базы данных MySQL
Это потребовало ряда приложений для преобразования таблиц во что-то полезное с использованием многих приемов, упомянутых здесь.
Если вы нашли это чрезвычайно полезным, выразите свою благодарность, проголосовав за него.
Также ознакомьтесь с другими моими статьями и официальными документами на сайте: www.coastrd.com
SET SESSION sql_mode='ANSI';
Команда, чтобы узнать, какие таблицы в данный момент находятся в кеше:
(Из блога о производительности MySQL )
источник
Команда, чтобы узнать, кто чем занимается:
И вы можете убить процесс с помощью:
источник
Мне особенно нравится встроенная поддержка MySQL для
inet_ntoa()
иinet_aton()
. Это делает обработку IP-адресов в таблицах очень простой (по крайней мере, если это только IPv4-адреса!)источник
Я люблю
on duplicate key
(AKA upsert, merge) за всевозможные счетчики, созданные лениво:Вы можете вставить много строк в один запрос и немедленно обработать повторяющийся индекс для каждой строки.
источник
Опять же - не совсем скрытые функции, но очень удобные:
Характерная черта
Легко захватить DDL:
SHOW CREATE TABLE CountryLanguage
вывод:
Функция: агрегатная функция GROUP_CONCAT () Создает объединенную строку своих аргументов для каждой детали и агрегирует путем объединения их для каждой группы.
Пример 1: простой
Вывод:
Пример 2: несколько аргументов
Вывод:
Пример 3: Использование настраиваемого разделителя
Вывод:
Пример 4: Управление порядком элементов списка
Вывод:
Функция: COUNT (DISTINCT) с несколькими выражениями
Вы можете использовать несколько выражений в выражении COUNT (DISTINCT ...) для подсчета количества комбинаций.
SELECT COUNT(DISTINCT CountryCode, Language) FROM CountryLanguage
Функция / Подсказка: нет необходимости включать неагрегированные выражения в список GROUP BY
Большинство реляционных СУБД применяют совместимую с SQL92 GROUP BY, которая требует, чтобы все неагрегированные выражения в списке SELECT отображались в GROUP BY. В этих СУБД этот оператор:
недействителен, потому что список SELECT содержит неагрегированный столбец Country.Continent, который не отображается в списке GROUP BY. В этих СУБД необходимо либо изменить список GROUP BY, чтобы читать
или вы должны добавить какой-нибудь бессмысленный агрегат в Country.Continent, например
Дело в том, что по логике нет ничего, что требовало бы объединения Country.Continent. Смотрите, Country.Code - это первичный ключ таблицы Country. Country.Continent также является столбцом из таблицы Country и, таким образом, по определению функционально зависит от первичного ключа Country.Code. Таким образом, в Country.Continent должно существовать ровно одно значение для каждой отдельной Country.Code. Если вы это понимаете, то понимаете, что не имеет смысла ни агрегировать его (есть только одно значение, верно), ни группировать по нему (так как это не сделает результат более уникальным, поскольку вы уже группируете по ПК)
В любом случае - MySQL позволяет вам включать неагрегированные столбцы в список SELECT, не требуя, чтобы вы также добавляли их в предложение GROUP BY.
Проблема в том, что MySQL не защищает вас в случае, если вы используете неагрегированный столбец. Итак, такой запрос:
Будет выполнено без претензий, но столбец CountryLanguage.Percentage будет содержать бессмысленные значения (то есть, из процентов всех языков одно из доступных значений процента будет выбрано случайным образом или, по крайней мере, вне вашего контроля.
См .: Развенчание группы мифами
источник
Команда "пейджер" в клиенте
Если у вас есть, скажем, 10 000 строк в вашем результате и вы хотите их просмотреть (это предполагает наличие команд «less» и «tee», что обычно имеет место в Linux; в Windows YMMV.)
И вы получите их в «меньшем» средстве просмотра файлов, чтобы вы могли легко пролистывать их, выполнять поиск и т. Д.
Также
Будет удобно записывать в файл.
источник
Некоторые вещи могут вас заинтересовать:
источник
Не скрытая функция, но тем не менее полезная: http://mtop.sourceforge.net/
источник
Вот несколько моих советов - я писал о них в своем блоге ( ссылка )
источник
Если вы собираетесь работать с большими и / или высокотранзакционными базами данных InnoDb, выучите и поймите блог Mysql Performance "ПОКАЗАТЬ СТАТУС INNODB" , он станет вашим другом.
источник
Если вы используете cmdline Mysq, вы можете взаимодействовать с командной строкой (на машинах Linux - не уверен, есть ли эквивалентный эффект в Windows), используя визг / восклицательный знак. Например:
отобразит код для file1.sql. Чтобы сохранить выписку и запрос в файл, используйте тройник
чтобы выключить это, используйте \ t
Наконец, чтобы запустить сценарий, который вы уже сохранили, используйте "имя файла источника". Конечно, нормальной альтернативой является указание имени скрипта при запуске mysql из командной строки:
Надеюсь, это кому-то пригодится!
Изменить: только что вспомнил еще один - при вызове mysql из командной строки вы можете использовать переключатель -t, чтобы вывод был в формате таблицы - настоящее благо для некоторых запросов (хотя, конечно, завершение запросов с помощью \ G, как упоминалось в другом месте, также полезно в этом отношении). Подробнее о различных переключателях Инструмент командной строки
Только что нашел изящный способ изменить порядок сортировки (обычно используйте Case ...). Если вы хотите изменить порядок сортировки (возможно, сортировать по 1, 4, 3, 2 вместо 1, 2, 3, 4) вы можете использовать функцию поля в предложении Order by. Например
Сортировать по полю (sort_field, 1,4,3,2)
источник
Я не думаю, что это специфично для MySQL, но меня просветляет:
Вместо того, чтобы писать
Ты можешь просто написать
источник
mysqlsla - один из наиболее часто используемых инструментов анализа журнала медленных запросов. Вы можете увидеть 10 самых худших запросов с тех пор, как вы последний раз выкатывали журналы медленных запросов. Он также может сказать вам, сколько раз был запущен BAD-запрос и сколько общего времени он занял на сервере.
источник
Фактически задокументировано , но очень раздражает: автоматическое преобразование неверных дат и другой неверный ввод.
Что касается дат: иногда вам «повезет», когда MySQL не настраивает ввод на близкие допустимые даты, а вместо этого сохраняет их как
0000-00-00
недопустимые по определению. Однако даже в этом случае вы могли бы захотеть, чтобы MySQL отказал, а не сохранял это значение для вас.источник
Встроенный профилировщик SQL .
источник
InnoDB по умолчанию хранит все таблицы в одном глобальном табличном пространстве, которое никогда не сжимается. .
Ты можешь использовать
innodb_file_per_table
который поместит каждую таблицу в отдельное табличное пространство, которое будет удалено при удалении таблицы или базы данных.Планируйте это заранее, так как в противном случае вам придется сделать дамп и восстановить базу данных, чтобы освободить место.
Использование табличных пространств для таблиц
источник
Если вы вставите в столбец datetime пустое строковое значение "", MySQL сохранит значение как 00/00/0000 00:00:00. В отличие от Oracle, который сохранит нулевое значение.
источник
Во время моих тестов с большими наборами данных и полями DATETIME всегда медленнее выполнять этот запрос:
Чем этот подход:
источник