Занимает ли пустое значение столбца то же пространство памяти, что и значение заполненного столбца?

15

У меня есть таблица с 2 столбцами. Тип обоих столбцов установлен в varchar(38). Если я создам строку с пустым значением для одного из столбцов, будет ли она занимать такое же место для хранения, как если бы это значение не было пустым?

Другими словами, будет ли MySQL резервировать место для хранения столбца (в зависимости от его типа) при создании строки?

Харис ур Рехман
источник

Ответы:

11

Из структуры физических рядов Innodb, пункт № 7 под REDUNDANT ROW_FORMAT

Значение SQL NULL резервирует один или два байта в каталоге записей. Кроме того, значение SQL NULL резервирует нулевые байты в части данных записи, если она хранится в столбце переменной длины . В столбце фиксированной длины он резервирует фиксированную длину столбца в части данных записи. Резервирование фиксированного пространства для значений NULL позволяет выполнить обновление столбца с NULL до значения, отличного от NULL, без фрагментации страницы индекса.

Из структуры физических рядов Innodb, пункт № 2 под COMPACT ROW_FORMAT

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

Основываясь на этих пунктах, вот что NULLпринимает значение для хранения столбца

  • переменная длина: значение NULL не занимает места в самой строке
  • фиксированная длина: занимает зарезервированное пространство

Теперь вы должны решить, использовать ли CHAR и VARCHAR из-за того, что выявил первый пункт

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

Это предотвратит любую фрагментацию строки, идущей в будущем, после сохранения данных, отличных от NULL. Это то, что я обсуждал ранее в отношении MyISAM: см. Мой старый пост. Какое влияние на производительность оказывает использование CHAR против VARCHAR в поле фиксированного размера? ,

RolandoMySQLDBA
источник
Привет, Роландо, я забыл упомянуть еще один момент - разницу в распределении памяти между объявлениями типов varchar (5) и varchar (100). Или действительно штраф, понесенный чрезмерным распределением.
Крейг Эфрейн
@CraigEfrein Вы обязательно должны добавить распределение памяти, что ваш ответ. (Кстати, я уже проголосовал за ваш ответ)
RolandoMySQLDBA
1
Наказание за перераспределение происходит, когда у вас есть комплекс, SELECTкоторый должен создать временную таблицу. Если это возможно, он будет использовать MEMORY, и конвертировать VARCHARв CHARдля таблицы TMP. Теперь VARCHAR(100)занимает фиксированные 100 (или 300) байтов, что может замедлить запрос.
Рик Джеймс
@RolandoMySQLDBA, Поведение, объясненное в вашем ответе, применимо для Mysql 5.7 DYNAMIC и COMPACT форматов строк.
Динеш Кумар
@DineshKumar Эти абзацы все еще находятся в 5.7 / 8.0 Документах. Пожалуйста, обратитесь к dev.mysql.com/doc/refman/5.7/en/innodb-row-format-dynamic.html для DYNAMIC.
RolandoMySQLDBA
8

Независимо от длины, определенной вами для столбца varchar, объем памяти, используемый пустым столбцом, будет одинаковым.

Типы CHAR и VARCHAR

введите описание изображения здесь

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

Как упоминает ypercube в своем комментарии, существуют дополнительные соображения относительно хранения строк в целом, когда присутствует хотя бы один обнуляемый столбец.

Innodb Физическая Структура Рядов

Часть переменной длины заголовка записи содержит битовый вектор для указания столбцов NULL. Если имеется от 9 до 15 столбцов, которые могут иметь значение NULL, битовый вектор использует два байта.)

...

Часть заголовка переменной длины также содержит длины столбцов переменной длины. Каждая длина занимает один или два байта, в зависимости от максимальной длины столбца. Если все столбцы в индексе NOT NULL и имеют фиксированную длину, заголовок записи не имеет части переменной длины

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

MySQL дает рекомендации по оптимизации хранения данных здесь: Оптимизация размера данных

Обновить

Еще одно соображение с varchar и это память. В MySQL важно максимально ограничить размер столбца переменной длины. Несмотря на то, что столбец является переменным, а используемое пространство хранения является переменным, MySQL выделит память в фиксированных чанках для хранения значений. Например, varchar (200) будет использовать больше памяти, чем varchar (5). Это не проблема с объемом памяти, но все же нужно учитывать при определении столбцов.

Крейг Эфрейн
источник
Числа выше предполагают CHARACTER SETlatin1 или ascii. Для utf8, Требуемый для хранения : CHAR(4)12.
Рик Джеймс