Я создал следующую таблицу:
CREATE TABLE dbo.TestStructure
(
id INT NOT NULL,
filler1 CHAR(36) NOT NULL,
filler2 CHAR(216) NOT NULL
);
а затем создал кластерный индекс:
CREATE CLUSTERED INDEX idx_cl_id
ON dbo.TestStructure(id);
Затем я заполнил его 30 строками, каждый размер которых составляет 256 байт (на основе объявления таблицы):
DECLARE @i AS int = 0;
WHILE @i < 30
BEGIN
SET @i = @i + 1;
INSERT INTO dbo.TestStructure (id, filler1, filler2)
VALUES (@i, 'a', 'b');
END;
Теперь, основываясь на информации, которую я прочитал в книге «Учебный комплект (экзамен 70-461): запросы к Microsoft SQL Server 2012 (Ицик Бен-Ган)»:
SQL Server внутренне организует данные в файле данных на страницах. Страница размером 8 Кбайт принадлежит одному объекту; например, к таблице или индексу. Страница - это самая маленькая единица чтения и записи. Страницы далее организованы в экстенты. Экстент состоит из восьми последовательных страниц. Страницы из экстента могут принадлежать одному объекту или нескольким объектам. Если страницы принадлежат нескольким объектам, тогда экстент называется смешанным экстентом; если страницы принадлежат одному объекту, то экстент называется равномерным экстентом. SQL Server хранит первые восемь страниц объекта в смешанных экстентах. Когда объект превышает восемь страниц, SQL Server выделяет дополнительные единообразные экстенты для этого объекта. Благодаря этой организации мелкие объекты тратят меньше места, а крупные объекты становятся менее фрагментированными.
Итак, здесь у меня есть первая смешанная страница экстента размером 8 КБ, заполненная 7680 байтами (я вставил 30 строк размера 256 байт, так что 30 * 256 = 7680), чтобы проверить размер, который я запустил, проверка размера proc - он возвращает следующий результат
index_type_desc: CLUSTERED INDEX
index_depth: 1
index_level: 0
page_count: 1
record_count: 30
avg_page_space_used_in_percent: 98.1961947121324
name : TestStructure
rows : 30
reserved : 16 KB
data : 8 KB
index_size : 8 KB
unused : 0 KB
Таким образом, 16 КБ зарезервировано для таблицы, первая страница 8 КБ предназначена для страницы корневого IAM, вторая страница предназначена для листовой страницы хранения данных, которая занимает 8 КБ и занимает ~ 7,5 КБ, теперь, когда я вставляю новую строку с 256 байт:
INSERT INTO dbo.TestStructure (id, filler1, filler2)
VALUES (1, 'a', 'b');
он не хранится на той же странице, хотя он имеет пространство 256 байт (7680 b + 256 = 7936, что по-прежнему меньше 8 КБ), создается новая страница данных, но эта новая строка может поместиться на той же старой странице Почему SQL Server создает новую страницу, когда он может сэкономить место и время поиска, вставляя ее в существующую страницу?
Примечание: то же самое происходит с индексом кучи.