Какой размер принимает значение «Null» в SQL Server

118

У меня есть большая таблица с 10 столбцами. 4 из них в большинстве случаев остаются нулевыми. У меня есть запрос, который имеет нулевое значение, принимает любой размер или не имеет размера в байтах. Я прочитал несколько статей, в которых говорится:

http://www.sql-server-citation.com/2009/12/common-mistakes-in-sql-server-part-4.html

Существует заблуждение, что если у нас есть значения NULL в таблице, она не занимает места для хранения. Дело в том, что значение NULL занимает место - 2 байта

SQL: использование значений NULL и значений по умолчанию

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

Не могли бы вы посоветовать мне размер нулевого значения.

Рокки Сингх
источник

Ответы:

146

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

Если поле переменной ширины, значение NULL не занимает места.

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


Причина обнаруженных вами неточностей в информации из других источников:

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

  • Вторая ссылка, похоже, касается Microsoft Access. Я не знаю подробностей того, как Access хранит NULL, но я не удивлюсь, если он отличается от SQL Server.

Марк Байерс
источник
1
@Mark "Верно, что для того, чтобы сделать столбец допускающим значение NULL, в хранилище что-то стоит, но как только вы это сделаете, для хранения NULL потребуется меньше места, чем для хранения значения (для столбцов переменной ширины)" Под этим вы имеете в виду чтобы сказать, что для переменных типов данных требуется 1 бит в качестве размера, занимаемого в памяти.
Рокки Сингх
13
Наименьшей адресуемой единицей памяти в большинстве компьютерных систем является единица byte(обычно 8 бит). Так что на самом деле a bitпринимает файл byte. Отличный ответ Марк: +1.
JohnB
20
Однако второй бит, третий бит и вплоть до восьмого бита помещаются в один и тот же байт.
Матти Вирккунен
1
@Mark - Да, это выглядит намного яснее. Извинения за исчезнувший комментарий. Я хотел исправить это, но мое интернет-соединение между удалением и отправкой прервалось! Это также немного зависит (из раздела комментариев здесь): «Для записи кучи и кластеризованного индекса всегда есть растровое изображение NULL. Для некластеризованных индексов не будет, если все столбцы в индексе НЕ NULL».
Мартин Смит
2
@ Мартин Смит: Я этого не знал. Это усложняет ситуацию, потому что, если я правильно понимаю, это означает, что создание столбца, допускающего значение NULL, не увеличивает требуемое пространство для хранения (поскольку нулевое растровое изображение всегда присутствует), если этот столбец также не находится в индексе, а другие столбцы в индексе не допускают значения NULL. В этом случае индекс теперь должен включать нулевое растровое изображение.
Марк Байерс
30

Следующие утверждения , что ссылка , если столбец является переменной длиной, т.е. varcharзатем NULLпринимает 0 байт (плюс 1 байты используются для флага , является ли значение NULLили нет):

В приведенной выше ссылке, а также в приведенной ниже ссылке, утверждается, что для столбцов фиксированной длины, т. Е. char(10)Или int, значение NULLзанимает длину столбца (плюс 1 байт, чтобы указать, является ли это значение NULLили нет):

Примеры:

  1. Если вы установите char(10)значение NULL, он занимает 10 байт (обнулен)
  2. An intзанимает 4 байта (также обнуленные).
  3. varchar(1 million)Набор для NULLзанимает 0 байт (+ 2 байта)

Примечание: при небольшом касании размер хранилища varcharравен длине введенных данных + 2 байта.

Johnb
источник
Разве varchar, хранящий NULL, не займет 0 + 2 + 1 (служебные данные NULL) байтов?
Акаш
Чтобы пометить NULL, должно быть + 1 бит . @Akash: 2 байта не нужны, поскольку растровое изображение уже помечает значение как NULL (никакая информация добавляться не будет).
Симо Кивистё
5

По этой ссылке :

Каждая строка имеет нулевое растровое изображение для столбцов, допускающих значения NULL. Если строка в этом столбце пуста, то бит в битовой карте равен 1, иначе это 0.

Для типов данных переменного размера фактический размер равен 0 байтам.

Для типа данных фиксированного размера фактический размер - это размер типа данных по умолчанию в байтах, установленный на значение по умолчанию (0 для чисел, '' для символов).

Кевин Лабранш
источник
Вы хотите сказать, что для таких типов данных, как nvarchar (max) varchar (max), Null будет принимать 0 байтов, а для int, chars и т.д. размер по умолчанию будет равен их значениям по умолчанию?
Rocky Singh
4

Сохранение значения NULL не занимает места.

«Дело в том, что значение NULL занимает место - 2 байта».

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

Значение NULL в базах данных - это системное значение, занимающее один байт памяти.

Речь идет о базах данных в целом, а не конкретно о SQL Server. SQL Server не использует 1 байт для хранения значений NULL.

Гейб
источник