Наборы символов MySQL char и varchar и размеры хранилища

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

CHAR(M) M × w байт, 0 ‹= M ‹= 255, где w — количество байтов, необходимое для символа максимальной длины в наборе символов.

VARCHAR(M), VARBINARY(M) L + 1 байт, если для значений столбца требуется от 0 до 255 байт, L + 2 байта, если для значений может потребоваться более 255 байт

Мне кажется, это означает, что для базы данных с кодировкой utf8 CHAR всегда будет занимать 32 бита на символ, тогда как VARCHAR будет занимать от 8 до 32 в зависимости от фактической длины хранимых символов в байтах. Это правильно? Или VARCHAR подразумевает 8-битную ширину символа, а хранение многооктетных символов UTF8 фактически использует несколько «символов» из VARCHAR? Или VARCHAR также всегда хранит 32 бита на символ? Так много возможностей.

Не то, о чем мне когда-либо приходилось беспокоиться раньше, но я начинаю сталкиваться с ограничениями размера временной таблицы в памяти, и я не обязательно хочу увеличивать доступный пул MySQL (во второй раз).


person pospi    schedule 10.04.2012    source источник


Ответы (1)


CHAR и VARCHAR оба подсчитывают символы. Оба они подсчитывают максимальное хранилище, которое им может потребоваться, с учетом кодировки символов и длины. Для ASCII это 1 байт на символ. Для UTF-8 это 3 байта на символ (а не 4, как можно было бы ожидать, потому что Поддержка Unicode в MySQL ограничена по какой-то причине, и он не поддерживает никаких символов Unicode, которые потребовали бы 4 байта в UTF-8). Пока что CHAR и VARCHAR одинаковы.

Теперь CHAR просто резервирует этот объем хранилища.

VARCHAR вместо этого выделяется 1 или 2 байта, в зависимости от того, является ли это максимальное хранилище ‹ 256 или ≥ 256. И фактический объем пространства, занимаемый записью, составляет эти один или два байта плюс объем пространства, фактически занимаемого строкой.

Интересно, что это делает 85 магическим числом для UTF-8 VARCHAR:

  • VARCHAR(85) использует 1 байт для длины, потому что максимально возможная длина 85 символов UTF-8 составляет 3 × 85 = 255.
  • VARCHAR(86) использует 2 байта для длины, потому что максимально возможная длина 86 символов UTF-8 составляет 3 × 86 = 258.
person Celada    schedule 10.04.2012
comment
Чтобы добавить к этому, хранилище MySQL utf8 не только повреждено, но и не является вашим стандартным UTF-8. Для хранения строк в кодировке utf8 требуется примерно в два раза больше памяти, чем для обычных строк в кодировке UTF-8, что делает его еще более неэффективным. - person deceze♦; 10.04.2012
comment
@deceze Я не знал об этом. У вас есть какие-либо подробности или ссылки на это? - person Celada; 10.04.2012
comment
Я бы хотел, но в документации об этом мало что говорится. Недавно здесь был задан вопрос о сбросе базы данных, где данные были сброшены в двоичном виде, как есть, и здесь это очень очевидно. - person deceze♦; 10.04.2012
comment
спасибо, ребята, это проливает свет на это. Интересна длина 85 символов в UTF8 - так что, в основном, обычный varchar (255) в базе данных, закодированной в utf8, вообще не экономит вам места? - person pospi; 16.04.2012
comment
Похоже, это сложнее, чем это. Например, InnoDB имеет два разных формата строк (COMPACT и REDUNDANT), поэтому пространство, занимаемое строкой, зависит от того, какая из них используется. Это уже не так просто, как когда-то, когда единственным широко используемым механизмом хранения был MyISAM. В любом случае, разница в 1 байт все равно незначительна. Вы, скорее всего, будете обеспокоены максимальной длиной ключа в InnoDB, которая составляет 768 байт. Таким образом, UTF-8 VARCHAR(256) не может быть частью ключа. Поле UTF-8 VARCHAR(255) может быть ключом. - person Celada; 16.04.2012
comment
Ах, сюжет сгущается .. полезно знать. Я также заметил, что в более поздних версиях MySQL доступна кодировка utf8mb4, которая является исправлением кодировки utf8, которую они использовали до этого момента. - person pospi; 17.04.2012