В чем разница между типами данных MySQL VARCHAR и TEXT?

19

После версии 5.0.3 (которая позволила VARCHAR быть 65 535 байт и перестала усекать конечные пробелы), есть ли существенное различие между этими двумя типами данных?

Я читал список различий, и только два примечания:

Для индексов в столбцах BLOB и TEXT необходимо указать длину префикса индекса. Для CHAR и VARCHAR длина префикса необязательна. См. Раздел 7.5.1, «Индексы столбцов».

и

Столбцы BLOB и TEXT не могут иметь значения DEFAULT.

Итак, из-за этих двух ограничений на тип данных TEXT, почему вы используете его поверх varchar (65535)? Есть ли последствия производительности одного над другим?

Дерек Дауни
источник
1
когда вы хотите более 65535 символов в данных?
BlackICE
Вот довольно хорошая ветка форума о тестах между varchar и текстом: http://forums.mysql.com/read.php?24,105964,105964
разделено
Поскольку этот список действительно хорошо показывает четкие детали, и поскольку у вас уже есть перечисленный список различий, я не уверен, что этот вопрос нам нужен в DBA. Есть ли причина, по которой список, который вы цитировали, и причины, которые вы дали , недостаточно хороши в этом случае? В противном случае я собираюсь на VtC
Jcolebrand
1
Я обновил свой вопрос, но одной очевидной причиной, в которой я не уверен, является производительность одного над другим. Не уверен, есть ли другие не столь очевидные причины
Дерек Дауни
Так справедливо ли то, что вы спрашиваете о характеристиках производительности одного над другим?
Jcolebrand

Ответы:

13

разделение связано с некоторой информацией, которая объясняет основную проблему (есть различия в производительности), но недостаточно просто сказать, что одно всегда лучше другого. (иначе, не было бы никакой причины иметь оба.) Кроме того, в MyISM максимальный размер 64 КБ для VARCHAR не для поля - это для каждой записи.

По сути, есть 4 способа хранения строк в записях базы данных:

  1. фиксированная длина
  2. Строки в стиле C (помеченные NULL или аналогичными символами в конце строки)
  3. Строки в стиле Pascal (несколько байтов для обозначения длины, затем строка)
  4. Указатели (храните строку где-то еще)

MyISM использует нечто похожее на # 3 для VARCHAR и гибридный подход для TEXT, где он сохраняет начало строки в записи, а затем остаток строки где-то еще. InnoDB аналогичен для VARCHAR, но сохраняет полное поле TEXT вне записи.

При использовании 1 и 4 материал в записи всегда имеет одинаковую длину, поэтому пропустить его проще, если вам не нужна строка, но вам нужно что-то после нее. И № 2, и № 3 не так уж плохи для коротких строк ... № 2 должен продолжать искать маркер, в то время как № 3 может пропустить вперед ... так как строки становятся длиннее, № 2 ухудшается для этого конкретного использования кейс.

Если вам действительно нужно прочитать строку, № 4 медленнее, поскольку вы должны прочитать запись, а затем прочитать строку, которая может храниться в другом месте на диске, в зависимости от того, как эта база данных обрабатывает ее. # 1 всегда довольно прост, и снова вы сталкиваетесь с похожими проблемами, где для # 2 тем хуже, чем длиннее строка, в то время как # 3 немного хуже, чем # 2 для очень маленьких строк, но лучше, когда становится длиннее.

Тогда есть требования к хранилищу ... # 1 всегда имеет фиксированную длину, поэтому он может иметь раздувание, если большинство строк не максимальной длины. # 2 имеет 1 дополнительный байт; # 3 обычно имеет 2 дополнительных байта, если максимальная длина = 255, 4 дополнительных байта, если максимум 64 КБ. # 4 имеет длину указателя, плюс правила для # 3 обычно.

Для определенных реализаций в MySQL 5.1 документы для состояния MyISM :

  • Поддержка истинного типа VARCHAR; столбец VARCHAR начинается с длины, хранящейся в одном или двух байтах.
  • Таблицы со столбцами VARCHAR могут иметь фиксированную или динамическую длину строки.
  • Сумма длин столбцов VARCHAR и CHAR в таблице может составлять до 64 КБ.

В то время как для InnoDB :

  • Часть переменной длины заголовка записи содержит битовый вектор для указания столбцов NULL. Если число столбцов в индексе, которое может быть NULL, равно N, битовый вектор занимает байты CEILING (N / 8). (Например, если есть от 9 до 15 столбцов, которые могут иметь значение NULL, битовый вектор использует два байта.) Столбцы с NULL не занимают места, отличного от бита в этом векторе. Часть заголовка переменной длины также содержит длины столбцов переменной длины. Каждая длина занимает один или два байта, в зависимости от максимальной длины столбца. Если все столбцы в индексе NOT NULL и имеют фиксированную длину, заголовок записи не имеет части переменной длины.
  • Для каждого поля переменной длины, отличного от NULL, заголовок записи содержит длину столбца в один или два байта. Два байта понадобятся только в том случае, если часть столбца хранится снаружи на страницах переполнения или максимальная длина превышает 255 байтов, а фактическая длина превышает 127 байтов. Для внешне сохраненного столбца двухбайтовая длина указывает длину внутренне сохраненной части плюс 20-байтовый указатель на внешне сохраненную часть. Внутренняя часть составляет 768 байт, поэтому длина составляет 768 + 20. 20-байтовый указатель хранит истинную длину столбца.

...

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

Джо
источник
Поток разделил связанные состояния, в которых MySQL хранит капли и текстовые поля inline forums.mysql.com/read.php?24,105964,267596#msg-267596
Майкл Миор,
1
Nitpick ... Для всех практических целей нет ограничения в 64 КБ для строки в любом Engine. LONGTEXTи LONGBLOBявляются показательным примером. Строки в стиле C нигде не используются MySQL (о чем я знаю). InnoDB действительно использует «гибридный» подход, но он более сложный, в зависимости от размера строки, row_format и т. Д. Хранение строк с «фиксированной» длиной почти никогда не рекомендуется, за исключением случаев, когда они на самом деле имеют постоянную длину (country_code, zip_code и т. Д.) , InnoDB имеет 4 ROW_FORMATs; В тексте обсуждаются только 1 или 2 из них.
Рик Джеймс
2

Когда SELECT необходимо создать временную таблицу (например, для сортировки результатов), он создаст либо таблицу MEMORY, либо таблицу MyISAM. ПАМЯТЬ более эффективна. Есть ограничения на ПАМЯТЬ - один из них запрещает ТЕКСТ и BLOB. Поэтому SELECT может работать медленнее с TEXT, чем VARCHAR.

Рик Джеймс
источник