У меня есть индексированный столбец, в котором хранится хэш MD5. Таким образом, столбец всегда будет хранить 32-символьное значение. По какой-то причине, он был создан как varchar, а не как char. Стоит ли переносить базу данных, чтобы преобразовать ее в символ? Это в MySQL 5.0 с InnoDB.
mysql
performance
innodb
varchar
Джейсон Бейкер
источник
источник
Ответы:
Подобный вопрос был задан ранее
Влияние на производительность размеров MySQL VARCHAR
Вот выдержка из моего ответа
Вы должны понять компромиссы использования CHAR против VARCHAR
С полями CHAR вы выделяете именно то, что получаете. Например, CHAR (15) выделяет и хранит 15 байтов, независимо от того, какие символы вы размещаете в поле. Работа со строками проста и понятна, поскольку размер поля данных полностью предсказуем.
С полями VARCHAR вы получите совершенно другую историю. Например, VARCHAR (15) фактически выделяет динамически до 16 байтов, до 15 для данных и, по крайней мере, 1 дополнительный байт для хранения длины данных. Если у вас есть строка 'hello' для хранения, которая будет занимать 6 байтов, а не 5. Во всех случаях при обработке строк всегда должна выполняться проверка длины.
Компромисс становится более очевидным, когда вы делаете две вещи: 1. Хранение миллионов или миллиардов строк. 2. Индексирование столбцов, которые являются CHAR или VARCHAR.
TRADEOFF # 1 Очевидно, что VARCHAR обладает преимуществом, поскольку данные переменной длины будут создавать меньшие строки и, следовательно, меньшие физические файлы.
TRADEOFF # 2 Поскольку поля CHAR требуют меньших манипуляций со строками из-за фиксированной ширины поля, поиск индекса по полю CHAR в среднем на 20% быстрее, чем поиск полей VARCHAR. Это не какая-то догадка с моей стороны. Книга MySQL Database Design and Tuning провела нечто удивительное на столе MyISAM, чтобы доказать это. Пример в книге сделал что-то вроде следующего:
Эта директива заставляет все VARCHAR вести себя как CHAR. Я сделал это на своей предыдущей работе в 2007 году, взял таблицу на 300 ГБ и ускорил поиск индекса на 20%, не меняя ничего другого. Он работал как опубликовано. Тем не менее, он дал таблицу почти в два раза больше, но это просто возвращает к компромиссу № 1.
Вы можете проанализировать хранимые данные, чтобы увидеть, что MySQL рекомендует для определения столбцов. Просто запустите следующее для любой таблицы:
Это будет проходить по всей таблице и рекомендовать определения столбцов для каждого столбца на основе содержащихся в нем данных, минимальных значений полей, максимальных значений полей и т. Д. Иногда вам просто нужно руководствоваться здравым смыслом при планировании CHAR против VARCHAR. Вот хороший пример:
Если вы храните IP-адреса, маска для такого столбца должна содержать не более 15 символов (xxx.xxx.xxx.xxx). Я бы сразу
CHAR(15)
понял, потому что длины IP-адресов не будут сильно меняться, а сложность манипулирования строками будет контролироваться дополнительным байтом. Вы все еще можете сделатьPROCEDURE ANALYSE()
против такой колонны. Может даже порекомендовать VARCHAR. В этом случае мои деньги все еще будут на CHAR, а не на VARCHAR.Проблемы CHAR и VARCHAR могут быть решены только путем правильного планирования. С большой силой приходит большая ответственность (клише, но это правда).
ОБНОВИТЬ
Когда дело доходит до MD5,
strlen
внутреннее вычисление должно быть исключено при переключении всего формата строки. Там не будет необходимости изменять определение поля.Если ключ MD5 - единственный присутствующий VARCHAR, я бы пошел на него и преобразовал формат строки таблицы в фиксированный . Если имеется большое количество других полей VARCHAR, они также выиграют. В обмен на это таблица расширилась бы примерно вдвое. Но запросы должны ускоряться примерно на 20% больше без дополнительной настройки.
источник
bit
и нетbinary
?Похоже, вы сэкономите 1 байт на значение или около 3%, преобразовав в a
char
. Вероятно, это того не стоит, если вы все равно храните MD5 в гексе - вы можете сэкономить 50%, используяbinary
вместо этого.Спасибо Ovais (см. Комментарии) за то, что он указал, что
char(32)
может использовать намного больше, чем 32 байта, если вы используете многобайтовый набор символов.Спасибо Рику Джеймсу за указание на то, что вы должны использовать
unhex
функцию для преобразования шестнадцатеричной строки в двоичную:дБ <> скрипка здесь
источник
binary
- или я неправильно понял?BINARY
очень мало, если вы также не используетеUNHEX()
. То есть, вы можете хранитьUNHEX(MD5(x))
в 16 байтBINARY(16)
значительно сэкономить пространство над хранениемMD5(x)
вCHAR(32) CHARACTER SET ascii
.Это не стоит менять на мой взгляд. Если вы посмотрите документацию здесь, это должно проиллюстрировать разницу между ними. В вашем сценарии использования одно не дает каких-либо существенных преимуществ по сравнению с другим, если вы действительно не беспокоитесь о дополнительных издержках, связанных с размером строки.
http://dev.mysql.com/doc/refman/5.0/en/char.html
Также обратите внимание на первый комментарий к документации, на которую я ссылаюсь выше ... «CHAR только ускорит ваш доступ, если вся запись имеет фиксированный размер. То есть, если вы используете какой-либо объект переменного размера, вы можете также сделать все из них». переменный размер. Вы не получаете скорости, используя CHAR в таблице, которая также содержит VARCHAR "
источник