Есть ли разница в производительности в MySQL между размерами varchar? Например, varchar(25)
и varchar(64000)
. Если нет, есть ли причина не объявлять все varchars с максимальным размером только для того, чтобы убедиться, что вам не хватит места?
Есть ли разница в производительности в MySQL между размерами varchar? Например, varchar(25)
и varchar(64000)
. Если нет, есть ли причина не объявлять все varchars с максимальным размером только для того, чтобы убедиться, что вам не хватит места?
Ответы:
Вы должны понять компромиссы использования CHAR против VARCHAR
С полями CHAR вы выделяете именно то, что получаете. Например, CHAR (15) выделяет и хранит 15 байтов, независимо от того, какие символы вы размещаете в поле. Работа со строками проста и понятна, поскольку размер поля данных полностью предсказуем.
С полями VARCHAR вы получите совершенно другую историю. Например, VARCHAR (15) фактически выделяет динамически до 16 байтов, до 15 для данных и, по крайней мере, 1 дополнительный байт для хранения длины данных. Если у вас есть строка 'hello' для хранения, которая будет занимать 6 байтов, а не 5. Во всех случаях при обработке строк всегда должна выполняться проверка длины.
Компромисс становится более очевидным, когда вы делаете две вещи:
1. Хранение миллионов или миллиардов строк.
2. Индексирование столбцов, которые являются CHAR или VARCHAR.
Очевидно, что VARCHAR обладает преимуществом, поскольку данные переменной длины будут создавать меньшие строки и, следовательно, меньшие физические файлы.
Поскольку поля CHAR требуют меньших манипуляций со строками из-за фиксированной ширины поля, поиск индекса по полю CHAR в среднем на 20% быстрее, чем поиск полей VARCHAR. Это не какая-то догадка с моей стороны. Книга MySQL Database Design and Tuning провела нечто удивительное на столе MyISAM, чтобы доказать это. Пример в книге сделал что-то вроде следующего:
ALTER TABLE tblname ROW_FORMAT=FIXED;
Эта директива заставляет VARCHAR вести себя как CHAR. Я сделал это на своей предыдущей работе в 2007 году, взял таблицу на 300 ГБ и ускорил поиск индекса на 20%, не меняя ничего другого. Он работал как опубликовано. Тем не менее, он дал таблицу почти в два раза больше, но это просто возвращает к компромиссу № 1.
Вы можете проанализировать хранимые данные, чтобы увидеть, что MySQL рекомендует для определения столбцов. Просто запустите следующее для любой таблицы:
SELECT * FROM tblname PROCEDURE ANALYSE();
Это будет проходить по всей таблице и рекомендовать определения столбцов для каждого столбца на основе содержащихся в нем данных, минимальных значений полей, максимальных значений полей и т. Д. Иногда вам просто нужно руководствоваться здравым смыслом при планировании CHAR против VARCHAR. Вот хороший пример:
Если вы храните IP-адреса, маска для такого столбца должна содержать не более 15 символов (xxx.xxx.xxx.xxx). Я бы сразу перешел к CHAR (15), потому что длины IP-адресов не будут сильно меняться, а сложность манипулирования строками будет контролироваться дополнительным байтом. Вы все еще можете выполнить АНАЛИЗ ПРОЦЕДУРЫ () для такого столбца. Может даже порекомендовать VARCHAR. В этом случае мои деньги все еще будут на CHAR, а не на VARCHAR.
Проблемы CHAR и VARCHAR могут быть решены только путем правильного планирования. С большой силой приходит большая ответственность (клише, но это правда)
Ответ на это на самом деле довольно сложный. Краткая версия: есть разница .
При создании временных таблиц для фильтрации результатов (например, GROUP BY
операторов) будет выделена полная длина.
Проводной протокол (отправка строк клиенту), вероятно, выделит большую длину.
Механизм хранения может / не может реализовать правильный varchar.
Для (2) я признаю, что проводной протокол не является чем-то, с чем я близко знаком, но общий совет здесь состоит в том, чтобы попытаться применить хотя бы некоторое минимальное усилие, чтобы угадать длину.
Большинству ответов в этой теме 5 лет, они написаны до того, как InnoDB и utf8 были значениями по умолчанию. Итак, позвольте мне начать все сначала ...
Когда запросу нужна внутренняя временная таблица, он пытается использовать MEMORY
таблицу. Но ПАМЯТЬ нельзя использовать, если
TEXT
/ BLOB
столбцы извлекаются, даже не TINYTEXT
.VARCHAR
больше некоторой суммы, вероятно, 512 в текущей версии.Также обратите внимание, что VARCHARs
превращаются в CHARs
. Таким образом, VARCHAR(255)
с CHARACTER SET utf8
расширением до 765 байтов, независимо от того, что находится в столбце. Затем это может быть вызвано:
MEMORY
таблица становится больше, чем либо, max_heap_table_size
либо tmp_table_size
она будет преобразована в MyISAM и потенциально попадет на диск.Так что, VARCHAR(25)
скорее всего, останется MEMORY
, значит, будет быстрее. (255)
не так хорошо, а (64000)
плохо.
(В будущем временные таблицы, вероятно, будут InnoDB
, и часть этого ответа потребуется пересмотреть.)
Столбец varchar такого размера повышает вероятность использования запросов во всей таблице во временных таблицах. Согласно книге High Performance MySQL. Когда оптимизатор пытается определить, может ли он выполнить этот запрос в памяти или ему нужна временная таблица, он смотрит на размер строки на основе определения таблицы, то есть для скорости он не пытается увидеть, сколько из 64К символов вы на самом деле используете. Вот почему авторы рекомендуют не расширять это определение за пределы фактических возможных значений, которые будут указаны в столбце. Очевидно, что если вы настроите себя на большее количество запросов, поступающих во временные таблицы (даже если фактический размер данных может уместиться в ОЗУ), вы теперь понесли штрафы за ввод-вывод, которых можно было бы избежать.
Насколько я понимаю, меньшие поля могут быть включены в индекс напрямую, а более длинные - нет. Из-за этого ограничения, если вы хотите, чтобы строки были индексируемыми, я бы сказал, чтобы они были короче. В противном случае, нет, так как они оба varchar, то операции сортировки или сравнения будут работать в одно и то же время, независимо от того, являются ли поля 25 или MAX.
убедитесь, что у вас нет места
Эта фраза подразумевает, что вы задаете вопрос, потому что не уверены в данных, которые будете хранить в базе данных. Если это правда, вам будет полезно выяснить это как можно скорее, потому что это понадобится вам для планирования загрузки. Например, если вы получаете элементы данных с 7000 символов, вам нужно знать об этом, поскольку это повлияет на производительность любой СУБД.
Тем не менее, я предпочитаю иметь размеры столбцов, связанные с ожидаемым содержанием. Например, номер телефона вряд ли будет длиннее 50 символов, даже если вы включите код страны и добавочный номер. Аналогичным образом почтовый индекс, скорее всего, будет состоять из 20 символов или менее.