Скрытые возможности MySQL

101

Я работаю с Microsoft SQL Server уже много лет, но только недавно начал использовать MySQL в своих веб-приложениях, и я жажду знаний.

Чтобы продолжить длинный ряд вопросов о «скрытых функциях » , я хотел бы знать любые скрытые или удобные функции MySQL, которые, надеюсь, улучшат мои знания об этой базе данных с открытым исходным кодом.

GateKiller
источник

Ответы:

161

Поскольку вы объявили награду, я поделюсь своими с трудом завоеванными секретами ...

В общем, все 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 virtualcolumnFROM 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

Майк Трейдер
источник
22

Один из не так скрытой особенностью MySQL является то , что это не очень хорошо быть SQL уступчивый, ну, не ошибки на самом деле, но, все больше подводных камней ... :-)

мат
источник
Сообщаем другим, что этот список оказался ценным при переходе от MSSQL к MySQL. Ура, Мат.
GateKiller
Многие из этих ошибок связаны с более ранними версиями MySQL.
jmucchiello
во-первых, я не думаю, что когда-либо удастся поместить значение NULL в поле отметки времени.
мат
3
MySQL не особенно хуже, чем многие другие базы данных, в плане совместимости с SQL; пока вы придерживаетесь разумного подмножества SQL, вы, как правило, можете избежать ошибок - это больше, чем можно сказать, например. Печально известные пустые строки NULL в Oracle.
bobince 01
1
Вы можете отключить некоторые из ошибокSET SESSION sql_mode='ANSI';
Kornel
21

Команда, чтобы узнать, какие таблицы в данный момент находятся в кеше:

mysql> SHOW open TABLES FROM test;
+----------+-------+--------+-------------+
| DATABASE | TABLE | In_use | Name_locked |
+----------+-------+--------+-------------+
| test     | a     |      3 |           0 |
+----------+-------+--------+-------------+
1 row IN SET (0.00 sec)

(Из блога о производительности MySQL )

Эран Гальперин
источник
15

Команда, чтобы узнать, кто чем занимается:

mysql> show processlist;
show processlist;
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
| Id | User        | Host            | db   | Command | Time | State                            | Info             |
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
|  1 | root        | localhost:32893 | NULL | Sleep   |    0 |                                  | NULL             |
|  5 | system user |                 | NULL | Connect |   98 | Waiting for master to send event | NULL             |
|  6 | system user |                 | NULL | Connect | 5018 | Reading event from the relay log | NULL             |
+-----+------+-----------+---------+---------+-------+-------+------------------+
3 rows in set (0.00 sec) 

И вы можете убить процесс с помощью:

mysql>kill 5 
Кристиан К. Сальвадо
источник
5
также ПОКАЗАТЬ ПОЛНЫЙ СПИСОК ПРОЦЕССОВ, если вы не хотите, чтобы запросы усекались.
Грег
11

Мне особенно нравится встроенная поддержка MySQL для inet_ntoa()и inet_aton(). Это делает обработку IP-адресов в таблицах очень простой (по крайней мере, если это только IPv4-адреса!)

Альнитак
источник
2
PostgreSQL имеет очень хороший тип inet, который очень хорошо обрабатывает ipv4 и ipv6 :-)
mat
Раньше они мне тоже нравились, но даже лучше не использовать их вообще. +1 для Postgres.
Kornel
11

Я люблю on duplicate key(AKA upsert, merge) за всевозможные счетчики, созданные лениво:

insert into occurances(word,count) values('foo',1),('bar',1) 
  on duplicate key cnt=cnt+1

Вы можете вставить много строк в один запрос и немедленно обработать повторяющийся индекс для каждой строки.

PorneL
источник
10

Опять же - не совсем скрытые функции, но очень удобные:

Характерная черта

Легко захватить DDL:

SHOW CREATE TABLE CountryLanguage

вывод:

CountryLanguage | CREATE TABLE countrylanguage (
  CountryCode char(3) NOT NULL DEFAULT '',
  Language char(30) NOT NULL DEFAULT '',
  IsOfficial enum('T','F') NOT NULL DEFAULT 'F',
  Percentage float(4,1) NOT NULL DEFAULT '0.0',
  PRIMARY KEY (CountryCode,Language)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

Функция: агрегатная функция GROUP_CONCAT () Создает объединенную строку своих аргументов для каждой детали и агрегирует путем объединения их для каждой группы.

Пример 1: простой

SELECT   CountryCode
,        GROUP_CONCAT(Language) AS List
FROM     CountryLanguage
GROUP BY CountryCode             

Вывод:

+-------------+------------------------------------+
| CountryCode | List                               |
+-------------+------------------------------------+
| ABW         | Dutch,English,Papiamento,Spanish   |
. ...         . ...                                .
| ZWE         | English,Ndebele,Nyanja,Shona       |
+-------------+------------------------------------+

Пример 2: несколько аргументов

SELECT   CountryCode
,        GROUP_CONCAT(
             Language
,            IF(IsOfficial='T', ' (Official)', '')
         )               AS List
FROM     CountryLanguage
GROUP BY CountryCode

Вывод:

+-------------+---------------------------------------------+
| CountryCode | List                                        |
+-------------+---------------------------------------------+
| ABW         | Dutch (Official),English,Papiamento,Spanish |
. ...         . ...                                         .
| ZWE         | English (Official),Ndebele,Nyanja,Shona     |
+-------------+---------------------------------------------+

Пример 3: Использование настраиваемого разделителя

SELECT   CountryCode
,        GROUP_CONCAT(Language SEPARATOR ' and ') AS List
FROM     CountryLanguage
GROUP BY CountryCode

Вывод:

+-------------+----------------------------------------------+
| CountryCode | List                                         |
+-------------+----------------------------------------------+
| ABW         | Dutch and English and Papiamento and Spanish |
. ...         . ...                                          .
| ZWE         | English and Ndebele and Nyanja and Shona     |
+-------------+----------------------------------------------+

Пример 4: Управление порядком элементов списка

SELECT   CountryCode
,        GROUP_CONCAT(
         Language
         ORDER BY CASE IsOfficial WHEN 'T' THEN 1 ELSE 2 END DESC
         ,        Language
         )               AS List
FROM     CountryLanguage
GROUP BY CountryCode

Вывод:

+-------------+------------------------------------+
| CountryCode | List                               |
+-------------+------------------------------------+
| ABW         | English,Papiamento,Spanish,Dutch,  |
. ...         . ...                                .
| ZWE         | Ndebele,Nyanja,Shona,English       |
+-------------+------------------------------------+

Функция: COUNT (DISTINCT) с несколькими выражениями

Вы можете использовать несколько выражений в выражении COUNT (DISTINCT ...) для подсчета количества комбинаций.

SELECT COUNT(DISTINCT CountryCode, Language) FROM CountryLanguage

Функция / Подсказка: нет необходимости включать неагрегированные выражения в список GROUP BY

Большинство реляционных СУБД применяют совместимую с SQL92 GROUP BY, которая требует, чтобы все неагрегированные выражения в списке SELECT отображались в GROUP BY. В этих СУБД этот оператор:

SELECT     Country.Code, Country.Continent, COUNT(CountryLanguage.Language)
FROM       CountryLanguage 
INNER JOIN Country 
ON         CountryLanguage.CountryCode = Country.Code
GROUP BY   Country.Code

недействителен, потому что список SELECT содержит неагрегированный столбец Country.Continent, который не отображается в списке GROUP BY. В этих СУБД необходимо либо изменить список GROUP BY, чтобы читать

GROUP BY   Country.Code, Country.Continent

или вы должны добавить какой-нибудь бессмысленный агрегат в Country.Continent, например

SELECT     Country.Code, MAX(Country.Continent), COUNT(CountryLanguage.Language)

Дело в том, что по логике нет ничего, что требовало бы объединения Country.Continent. Смотрите, Country.Code - это первичный ключ таблицы Country. Country.Continent также является столбцом из таблицы Country и, таким образом, по определению функционально зависит от первичного ключа Country.Code. Таким образом, в Country.Continent должно существовать ровно одно значение для каждой отдельной Country.Code. Если вы это понимаете, то понимаете, что не имеет смысла ни агрегировать его (есть только одно значение, верно), ни группировать по нему (так как это не сделает результат более уникальным, поскольку вы уже группируете по ПК)

В любом случае - MySQL позволяет вам включать неагрегированные столбцы в список SELECT, не требуя, чтобы вы также добавляли их в предложение GROUP BY.

Проблема в том, что MySQL не защищает вас в случае, если вы используете неагрегированный столбец. Итак, такой запрос:

SELECT     Country.Code, COUNT(CountryLanguage.Language), CountryLanguage.Percentage
FROM       CountryLanguage 
INNER JOIN Country 
ON         CountryLanguage.CountryCode = Country.Code
GROUP BY   Country.Code

Будет выполнено без претензий, но столбец CountryLanguage.Percentage будет содержать бессмысленные значения (то есть, из процентов всех языков одно из доступных значений процента будет выбрано случайным образом или, по крайней мере, вне вашего контроля.

См .: Развенчание группы мифами

анон.
источник
Разрешение столбцов, не объявленных в group by, - одна из моих наименее любимых функций Oracle. Если вы привыкли к Oracle, это большая проблема - он просто позволяет вам выполнять запрос, результаты выглядят правильно, но затем вы понимаете, что он не выполняет то, что вы думали.
mbafford
7

Команда "пейджер" в клиенте

Если у вас есть, скажем, 10 000 строк в вашем результате и вы хотите их просмотреть (это предполагает наличие команд «less» и «tee», что обычно имеет место в Linux; в Windows YMMV.)

pager less
select lots_of_stuff FROM tbl WHERE clause_which_matches_10k_rows;

И вы получите их в «меньшем» средстве просмотра файлов, чтобы вы могли легко пролистывать их, выполнять поиск и т. Д.

Также

pager tee myfile.txt
select a_few_things FROM tbl WHERE i_want_to_save_output_to_a_file;

Будет удобно записывать в файл.

MarkR
источник
к сожалению, под Windows, даже если существуют "меньше" и "тройник", сама опция пейджера не поддерживается. в любом случае не легко
Берри Цакала
6

Некоторые вещи могут вас заинтересовать:

<query>\G -- \G in the CLI instead of the ; will show one column per row
explain <query>; -- this will show the execution plan for the query
Сорин В.
источник
3

Вот несколько моих советов - я писал о них в своем блоге ( ссылка )

  1. Вам не нужно использовать знак «@» при объявлении переменных.
  2. Вы должны использовать разделитель (по умолчанию ';'), чтобы обозначить конец оператора - Ссылка
  3. Если вы пытаетесь переместить данные между MS-SQL 2005 и mySQL, есть несколько препятствий, которые нужно пройти - Ссылка
  4. Выполнение совпадений с учетом регистра в mySQL - ссылка
Нихил
источник
3

Если вы собираетесь работать с большими и / или высокотранзакционными базами данных InnoDb, выучите и поймите блог Mysql Performance "ПОКАЗАТЬ СТАТУС INNODB" , он станет вашим другом.

Хок Крегер
источник
3

Если вы используете cmdline Mysq, вы можете взаимодействовать с командной строкой (на машинах Linux - не уверен, есть ли эквивалентный эффект в Windows), используя визг / восклицательный знак. Например:

\! cat file1.sql

отобразит код для file1.sql. Чтобы сохранить выписку и запрос в файл, используйте тройник

\T filename

чтобы выключить это, используйте \ t

Наконец, чтобы запустить сценарий, который вы уже сохранили, используйте "имя файла источника". Конечно, нормальной альтернативой является указание имени скрипта при запуске mysql из командной строки:

    mysql -u root -p < case1.sql

Надеюсь, это кому-то пригодится!

Изменить: только что вспомнил еще один - при вызове mysql из командной строки вы можете использовать переключатель -t, чтобы вывод был в формате таблицы - настоящее благо для некоторых запросов (хотя, конечно, завершение запросов с помощью \ G, как упоминалось в другом месте, также полезно в этом отношении). Подробнее о различных переключателях Инструмент командной строки

Только что нашел изящный способ изменить порядок сортировки (обычно используйте Case ...). Если вы хотите изменить порядок сортировки (возможно, сортировать по 1, 4, 3, 2 вместо 1, 2, 3, 4) вы можете использовать функцию поля в предложении Order by. Например

Сортировать по полю (sort_field, 1,4,3,2)

DBMarcos99
источник
3

Я не думаю, что это специфично для MySQL, но меня просветляет:

Вместо того, чтобы писать

WHERE (x.id > y.id) OR (x.id = y.id AND x.f2 > y.f2) 

Ты можешь просто написать

WHERE (x.id, x.f2) > (y.id, y.f2)
Йохан
источник
Это действительно круто, но какие варианты использования могут быть для этого?
mangoDrunk
Это может быть полезно для поиска всех записей, которые больше, чем данная запись.
Fantius
2

mysqlsla - один из наиболее часто используемых инструментов анализа журнала медленных запросов. Вы можете увидеть 10 самых худших запросов с тех пор, как вы последний раз выкатывали журналы медленных запросов. Он также может сказать вам, сколько раз был запущен BAD-запрос и сколько общего времени он занял на сервере.

паван
источник
2

Фактически задокументировано , но очень раздражает: автоматическое преобразование неверных дат и другой неверный ввод.

До MySQL 5.0.2 MySQL прощал недопустимые или неправильные значения данных и принуждает их к допустимым значениям для ввода данных. В MySQL 5.0.2 и выше это остается поведением по умолчанию, но вы можете изменить режим SQL сервера, чтобы выбрать более традиционную обработку неверных значений, так что сервер отклоняет их и прерывает оператор, в котором они возникают.

Что касается дат: иногда вам «повезет», когда MySQL не настраивает ввод на близкие допустимые даты, а вместо этого сохраняет их как 0000-00-00недопустимые по определению. Однако даже в этом случае вы могли бы захотеть, чтобы MySQL отказал, а не сохранял это значение для вас.

Арджан
источник
1

InnoDB по умолчанию хранит все таблицы в одном глобальном табличном пространстве, которое никогда не сжимается. .

Ты можешь использовать innodb_file_per_table который поместит каждую таблицу в отдельное табличное пространство, которое будет удалено при удалении таблицы или базы данных.

Планируйте это заранее, так как в противном случае вам придется сделать дамп и восстановить базу данных, чтобы освободить место.

Использование табличных пространств для таблиц

сербаут
источник
1

Если вы вставите в столбец datetime пустое строковое значение "", MySQL сохранит значение как 00/00/0000 00:00:00. В отличие от Oracle, который сохранит нулевое значение.

Devid G
источник
1

Во время моих тестов с большими наборами данных и полями DATETIME всегда медленнее выполнять этот запрос:

SELECT * FROM mytable
WHERE date(date_colum) BETWEEN '2011-01-01' AND ''2011-03-03';

Чем этот подход:

SELECT * FROM mytable
WHERE date_column BETWEEN '2011-01-01 00:00:00' AND '2011-03-03 23:59:59'
Освальдо Меркадо
источник