Выбор типа данных для MySQL? - PullRequest
7 голосов
/ 08 апреля 2011

Я изучал и читал о типах данных SQL в течение нескольких дней (я знаю ... я знаю, что это не очень долго), и одна из вещей, которую мне трудно понять, это как выбрать лучшийтип данных для расширяемости, эффективности и простоты доступа.

Я думаю, что довольно просто выбрать базовые типы данных (например, int vs varchar), но как выбирать между такими вещами, как blob и text type.

Man-страницы MySQL хороши, ноони не то, что мы, компьютерные фанаты, любим ... эффективные.

Я думаю, было бы здорово, если бы мы могли составить список типов данных MySQL, общие преимущества / недостатки каждого из них и когда это имело бы смыслвыбрать этот тип данных.

Ответы [ 3 ]

11 голосов
/ 11 апреля 2011

Типы строк MySQL представлены в двух вариантах: один без метки набора символов и один с меткой набора символов.

Строка фиксированной длины, дополненная пробелами в конце, - это CHAR (n). Тип соответствия, у которого нет метки набора символов, - BINARY (n). Сохранение строки "hello" в CHAR(255) CHARSET utf8 займет 765 байт (строка, дополненная пробелами до полной длины, хранится как utf8, которая в худшем случае использует пространство 3 байта / символ, выделяющее 3 * 255 байт).

Строка переменной длины с одним или двумя байтами длины и без заполнения - VARCHAR ((n). Тип соответствия, у которого нет метки набора символов, - VARBINARY (n). Сохранение строки "hello" в VARCHAR(255) CHARSET utf8 будет занимает 6 байт (1 байт длины плюс 5 байт для фактического текста). Сохранение строки ク リ ス в том же типе займет 10 байт (1 байт длины плюс 3 символа, используя 3 байта на символ для их представления).

mysql> select hex('クリス'), length(hex('クリス'))/2 as bytes;
+--------------------+--------+
| hex('クリス')      | bytes  |
+--------------------+--------+
| E382AFE383AAE382B9 | 9.0000 |
+--------------------+--------+
1 row in set (0.02 sec)

Строка переменной длины с одним, двумя, тремя или четырьмя байтами длины - это TINYTEXT, TEXT, MEDIUMTEXT и LARGETEXT. Типы соответствия, у которых нет метки набора символов: TINYBLOB, BLOB, MEDIUMBLOB и LARGEBLOB.

TEXT / BLOB-подобный тип отличается от VARCHAR / VARBINARY-подобного типа тем, как и где хранятся данные, подробности о том, как TEXT / BLOB-подобные типы хранятся в InnoDB, см. В http://www.mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb/ по версии и настройкам ROW_FORMAT. Из соображений производительности вам нужна последняя версия таблиц InnoDB и "Barracuda".

MySQL не способен работать с любыми данными, размер которых превышает max_allowed_packet (по умолчанию: 1M), если вы не создадите сложные и интенсивно использующие память обходные пути на стороне сервера. Это дополнительно ограничивает то, что может быть сделано с TEXT / BLOB-подобными типами, и обычно делает тип LARGETEXT / LARGEBLOB бесполезным в конфигурации по умолчанию.

Для типов без метки набора символов (BINARY, VARBINARY и% BLOB%) MySQL будет принимать данные как полученные и записывать их на диск. Для типов с меткой набора символов MySQL будет смотреть на то, что вы объявили в качестве набора символов клиента для сервера с SET NAMES, и что такое метка набора символов, определенная в столбцах. Затем он преобразует из набора символов соединения в набор символов столбца и записывает преобразованные данные. Вы можете проверить это с помощью функции HEX (), например, SELECT HEX(str) FROM t WHERE id = ....

При поиске объявленный набор символов с SET NAMES может отличаться от того, который был во время записи. MySQL снова проверит метку набора символов столбцов относительно набора символов, объявленного для этого подключения, и при необходимости преобразует в набор символов подключения.

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


Часто задаваемый вопрос: должен ли я выбрать CHAR или VARCHAR (BINARY или VARBINARY соответственно)?

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


Еще один связанный вопрос: я должен выбрать VARCHAR или TEXT для моих строк (VARBINARY или BLOB, соответственно)?

Ответом для этого является использование последней версии InnoDB, таблиц формата Barracuda, а затем TEXT / BLOB.Причина этого подробно объясняется в http://www.mysqlperformanceblog.com/2011/04/07/innodb-row-size-limitation/.. Результат этого: с VARCHAR или TEXT / BLOB в формате pre-Barracuda вы рискуете переполнить ограничение размера строки InnoDB, если у вас слишком многоих в одну строку.


И, наконец: Должен ли я хранить файлы / изображения / другие большие большие двоичные объекты или текстовые данные в базе данных?

Ответ таков: обычно нет.Обслуживание файлов из базы данных (http://mysqldump.azundris.com/archives/36-Serving-Images-From-A-Database.html) - дорогостоящая операция по сравнению с обслуживанием файлов из файловой системы. Если это вообще возможно, вы захотите сделать это вместо этого. Есть способ обойти это, http://www.blobstreaming.org/, но это продвинутая технология, которая требует полного контроля над средой выполнения, чего никогда не бывает в размещенной среде.


В заключение: в данных нет типов данных переменной длины.Таблицы механизма MEMORY. Так что если вы видите «использование временного» в выводе EXPLAIN, это означает, что

  • VARCHAR преобразуется в CHAR в этой временной таблице
  • VARBINARY преобразуется вBINARY

Если временная таблица этого процесса становится больше, чем tmp_table_size ИЛИ max_heap_table_size, она на лету преобразуется в формат MyISAM и отправляется на диск.

Пример: вы определяетеКласс * Ruby Active Record User содержит десять полей, помеченных как :string. Каждое из них заканчивается VARCHAR(255) CHARSET utf8 в вашей таблице Users,

В другом месте вашей кодовой базы Users используется таким образом, что включает план using temporary.Вы мгновенно умираете в дисковых операциях под нагрузкой, потому что каждая строка таблицы Users теперь использует как минимум 7650 байт в MEMORY, большинство из которых являются пробелами, используемыми в качестве заполнения.Это вынуждает временную таблицу преобразовываться в MyISAM и записывать на диск.

  • любой тип% TEXT% или% BLOB% не может быть представлен в MEMORY, поэтому временная таблица отправляется на диск как MyISAM, даже еслион был бы достаточно мал для хранения в памяти в соответствии с указанными выше ограничениями.

Это означает, что любой запрос с типом TEXT или BLOB и планом с «использованием временного» необходимо переписатьво избежание попадания временных таблиц на диск.

1 голос
/ 29 ноября 2016

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

Быстрый динамический сценарий concat для генерации SQL для запуска

select CONCAT(' SELECT ', COLUMN_NAME, ' FROM ', TABLE_NAME, ' procedure analyse() ;' ) 
FROM INFORMATION_SCHEMA.COLUMNS   
WHERE table_schema ="yourDbName"   
AND DATA_TYPE ="varchar"   
AND CHARACTER_MAXIMUM_LENGTH > 190   
AND COLUMN_KEY not in (' ') ;

** SQL выше не оценивает PK - при условии, что они не являются текстовыми полями

Эта процедура полезна, когда нужно изменить тип данных в зависимости от использования данных или повысить эффективность за счет перемещения или хранения меньшего пакета данных.

В блоге Percona есть хороший рабочий пример анализа процедур, применимый к Drupal. https://www.percona.com/blog/2009/03/23/procedure-analyse/

Некоторые из этих исследований сделаны для сжатия, которое связано с более длинными индексами utf8mb4. http://techblog.constantcontact.com/devops/space-the-final-frontier-a-story-of-mysql-compression/

1 голос
/ 10 апреля 2011

Что касается BLOB против TEXT (поскольку это единственный конкретный вопрос в вашем посте): BLOB предназначен для двоичных данных, а TEXT предназначен для текстовых данных.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...