Я створив таку таблицю:
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 (Itzik Ben-Gan)":
SQL Server внутрішньо впорядковує дані у файл даних на сторінках. Сторінка є одиницею 8 Кб і належить до одного об’єкта; наприклад, до таблиці чи індексу. Сторінка - найменша одиниця читання та письма. Далі сторінки впорядковані в розширення. Обсяг складається з восьми послідовних сторінок. Сторінки в тій чи іншій мірі можуть належати одному об'єкту або декільком об'єктам. Якщо сторінки належать до декількох об'єктів, то міру називають змішаною мірою; якщо сторінки належать одному об’єкту, то обсяг називається рівномірним масштабом. SQL Server зберігає перші вісім сторінок об'єкта в змішаних формах. Коли об'єкт перевищує вісім сторінок, SQL Server виділяє додаткові рівномірні розширення для цього об’єкта. Завдяки цій організації дрібні об’єкти витрачають менше місця, а великі об'єкти менш фрагментовані.
Отже, у мене є перша змішана сторінка розміром 8 КБ, заповнена 7680 байтами (я вставив 30 разів 256 байт рядка розміру, тому 30 * 256 = 7680), щоб перевірити розмір, у якого я запустив розмір, перевірити проц - він повертає наступний результат
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 Кб сторінка призначена для сторінки Root IAM, друга - для сторінки зберігання листкових даних, яка становить 8 КБ із зайнятістю ~ 7,5 КБ, тепер, коли я вставляю новий рядок із 256 байтами:
INSERT INTO dbo.TestStructure (id, filler1, filler2)
VALUES (1, 'a', 'b');
вона не зберігається на одній сторінці, хоча вона має простір у 256 байт (7680 b + 256 = 7936, який все ще менший, ніж 8 КБ), створюється нова сторінка даних, але цей новий рядок міг би бути розміщений на тій же старій сторінці , чому SQL Server створює нову сторінку, коли вона може заощадити простір і час пошуку, купивши вставити її на існуючу сторінку?
Примітка: те саме відбувається в індексі купи.