Null Bitmap хранят в себе информацию о том, какие столбцы в записи имеют значение null. Это сделано в целях повышения производительности и позволяет избавиться от чтения всех записей центральным процессором когда нулловые столбцы присутствуют в списке выборки – это позволяет минимизировать использование кэша процессора (здесь можно почитать о работе кэшей процессора и о MESI протоколе). И всвязи с этим, существует три мифа, которые будут развенчаны прямо сейчас:
Миф №6a – Null Bitmap создаётся не всегда
FALSE
Null Bitmap *всегда* существует в каждой записи данных (в куче, или на листовом уровне кластерного индекса) – даже если таблица не содержит нулловых столбцов. В то же время Null Bitmap *не* всегда присутствует в индексных записях (листовой уровень некластерного индекса, не листовой уровень кластерного и некластерного индекса).
Всё это довольно легко проверить при помощи следующего скрипта:
CREATE TABLE NullTest (c1 INT NOT NULL);
CREATE NONCLUSTERED INDEX
NullTest_NC ON NullTest (c1);
GO
INSERT INTO NullTest VALUES (1);
GO
EXEC sp_allocationMetadata 'NullTest';
GO
Используйте ID страницы, полученные в результате выполнения sp_allocationMetadata (столбец First Page), в следующем скрипте:
DBCC TRACEON (3604);
DBCC PAGE (foo, 1, 152, 3); -- page ID from SP output
where Index ID = 0
DBCC PAGE (foo, 1, 154, 1); -- page ID from SP output
where Index ID = 2
GO
Примечание: синтаксис DBCC PAGE: DBCC PAGE('имя_базы_данных' | id_базы_данных, номер_файла, номер_страницы, формат).
Подробнее о DBCC PAGE можно почитать здесь – How to use DBCC PAGE. В выводе sp_allocationMetadata First Page будет
представлена в следующем виде: (1:80), где 1– номер файла, 80– номер страницы.
Теперь смотрим на первый дамп DBCC PAGE, который соответствует записи кучи:
Slot 0 Offset 0x60 Length 11
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
Memory Dump @0x685DC060
И на второй, соответствующий записи некластерного индекса:
Slot 0, Offset 0x60, Length 13, DumpStyle BYTE
Record Type = INDEX_RECORD Record Attributes = <<<<<<< No null bitmap
Memory Dump @0x685DC060
Миф №6b – Null Bitmap содержит биты только для нулловых колонок
FALSE
Null Bitmap, когда существует, содержит по биту на каждую колонку, плюс 'заполняющие' биты для несуществующих полей для того, чтобы полностью заполнить байт в Null Bitmap. Я уже развенчивал этот миф в своём старом посте - Misconceptions around null bitmap size.
Миф №6c – Добавление в таблицу новой строки приводит к немедленному выполнению size-of-data операции
FALSE
Единственный случай, когда добавление в таблицу нового поля приводит к выполнению
size-of-data операции (операции, которая затрагивает каждую строку таблицы) это добавление столбца, имеющего значение по умолчанию отличное от NULL. В остальных случаях Storage Engine запоминает что есть один или несколько столбцов, которые в действительности могут не присутствовать в записях таблицы. Я объяснял это более детально в своём посте
Misconceptions around adding columns to a table.
Об авторе:
Пол С. Рэндал (Paul S. Randal) — генеральный директор SQLskills.com является MVP по SQL Server. Он работал в группе подсистемы хранилища SQL Server в корпорации Майкрософт с 1999 по 2007 г. Пол является автором DBCC CHECKDB/восстановления SQL Server 2005 и в ходе разработки SQL Server 2008 отвечал за программу базовой подсистемы хранилища. Пол является специалистом по аварийному восстановлению, высокой доступности и обслуживанию базы данных и часто дает презентации на различных конференциях по всему миру. Он ведет блог по адресу SQLskills.com/blogs/paul.
Ссылки по теме:
- Оригинал статьи
- Misconceptions around null bitmap size
- Misconceptions around adding columns to a table
- How to use DBCC PAGE
- Ковыряем DBCC PAGE