NULL в MySQL (производительность и хранение)

Что именно делает NULL для производительности и хранения (пробела) мудрым в MySQL?

Например:

TINYINT: 1 байт TINYINT w/NULL 1 байт + как-то хранит NULL?

Ответ 1

Это зависит от того, какой механизм хранения вы используете.

В формате MyISAM каждый заголовок строки содержит битовое поле с одним битом для каждого столбца для кодирования состояния NULL. Столбец с номером NULL по-прежнему занимает пробел, поэтому NULL не уменьшает объем памяти. См. https://dev.mysql.com/doc/internals/en/myisam-introduction.html

В InnoDB каждый столбец имеет "смещение начала поля" в заголовке строки, который представляет собой один или два байта на столбец. Высокий бит в этом начальном смещении поля включен, если столбец равен NULL. В этом случае столбец не нужно хранить вообще. Поэтому, если у вас много NULL, ваше хранилище должно быть значительно уменьшено. См. https://dev.mysql.com/doc/internals/en/innodb-field-contents.html

EDIT:

Бит NULL являются частью заголовков строк, вы не хотите их добавлять.

Единственный способ, которым я могу представить, что NULL повышает производительность, - это то, что в InnoDB страница данных может поместиться больше строк, если строки содержат NULL. Таким образом, ваши буферы InnoDB могут быть более эффективными.

Но я был бы очень удивлен, если бы это обеспечило значительное преимущество в производительности на практике. Беспокойство о влиянии NULL на производительность находится в сфере микро-оптимизации. Вы должны сосредоточить свое внимание в другом месте, в областях, которые дают больший удар для доллара. Например, добавление хорошо отобранных индексов или увеличение выделения кэша базы данных.

Ответ 2

Ответ на ответ хороший, но немного устаревший. Использование одного или двух байтов для хранения NULL применяет только к формату строки InnoDB REDUNDANT. Поскольку MySQL 5.0.3 InnoDB использует формат строки COMPACT, который использует только один бит для хранения NULL (конечно, один байт является минимальным), поэтому:

Необходимое пространство для NULL = ПОТОЛОК (N/8) байтов, где N - количество столбцов NULL в строке.

  • 0 NULLS = 0 байт
  • 1 - 8 NULLS = 1 байт
  • 9 - 16 NULLS = 2 байта
  • 17 - 24 NULLS = 3 байта
  • и т.д.

Согласно официальному сайту MySQL о COMPACT и REDUNDANT:

Компактный формат строки уменьшает пространство для хранения строк примерно на 20% за счет увеличения использования ЦП для некоторых операций. Если ваша рабочая нагрузка является типичной, которая ограничена скоростью попадания кэш-памяти и скоростью диска, компактный формат, скорее всего, будет быстрее.

Преимущество использования NULLS над пустыми строками или нулями:

  • 1 NULL требует 1 байт
  • 1 Пустая строка требует 1 байт (при условии, что VARCHAR)
  • 1 Нуль требует 4 байта (при условии INT)

Вы начинаете видеть сбережения здесь:

  • 8 NULL требуют 1 байт
  • 8 Пустые строки требуют 8 байт
  • 8 нулей требуется 32 байта

С другой стороны, я предлагаю использовать NULL по пустым строкам или нулям, потому что они более организованные, портативные и требуют меньше места. Чтобы повысить производительность и сэкономить место, сосредоточьтесь на использовании правильных типов данных, индексов и запросов вместо странных трюков.

Подробнее о: https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html

Ответ 3

Я согласен с Биллом Карвином, хотя я бы добавил эти советы MySQL. Номер 11 обращается к этому конкретно:

Прежде всего, спросите себя, есть ли разница между наличием пустого строкового значения и значением NULL (для полей INT: 0 или NULL). Если нет причин иметь оба, вам не нужно поле NULL. (Знаете ли вы, что Oracle считает NULL и пустую строку одной и той же?)

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

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

Обновление Повторяя это позже, я бы добавил, что лично мне не нравится использовать 0 вместо NULL в базе данных, и я не рекомендую его. Это может легко привести к множеству ложных срабатываний в вашем приложении, если вы не будете осторожны.

Ответ 5

dev.mysql.com/doc/refman/5.0/en/is-null-optimization.html

MySQL может выполнять ту же оптимизацию на col_name IS NULL, что он может использовать для col_name = constant_value. Например, MySQL может использовать индексы и диапазоны для поиска NULL с IS NULL