Ho creato la seguente tabella:
CREATE TABLE dbo.TestStructure
(
id INT NOT NULL,
filler1 CHAR(36) NOT NULL,
filler2 CHAR(216) NOT NULL
);
e quindi creato un indice cluster:
CREATE CLUSTERED INDEX idx_cl_id
ON dbo.TestStructure(id);
Successivamente l'ho popolato con 30 righe ogni dimensione è 256 byte (in base alla dichiarazione della tabella):
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;
Ora basato sulle informazioni che ho letto nel "Kit di formazione (Esame 70-461): Interrogazione del libro Microsoft SQL Server 2012 (Itzik Ben-Gan)":
SQL Server organizza internamente i dati in un file di dati in pagine. Una pagina è un'unità da 8 KB e appartiene a un singolo oggetto; ad esempio, a una tabella o un indice. Una pagina è la più piccola unità di lettura e scrittura. Le pagine sono ulteriormente organizzate in estensione. Un'estensione è composta da otto pagine consecutive. Le pagine di un'estensione possono appartenere a un singolo oggetto o a più oggetti. Se le pagine appartengono a più oggetti, l'estensione viene chiamata estensione mista; se le pagine appartengono a un singolo oggetto, l'estensione viene definita estensione uniforme. SQL Server archivia le prime otto pagine di un oggetto in estensioni miste. Quando un oggetto supera le otto pagine, SQL Server alloca ulteriori estensioni uniformi per questo oggetto. Con questa organizzazione, i piccoli oggetti sprecano meno spazio e gli oggetti più grandi sono meno frammentati.
Quindi qui ho la prima pagina di 8 KB di dimensioni miste, popolata con 7680 byte (ho inserito 30 volte 256 byte di dimensione riga, quindi 30 * 256 = 7680), per verificare la dimensione che ho eseguito proc verifica dimensioni - restituisce il seguente risultato
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
Quindi 16 KB sono riservati per la tabella, la prima pagina da 8 KB è per la pagina Root IAM, la seconda è per la pagina di archiviazione dei dati foglia che è 8KB con un'occupazione di ~ 7.5 KB, ora quando inserisco una nuova riga con 256 byte:
INSERT INTO dbo.TestStructure (id, filler1, filler2)
VALUES (1, 'a', 'b');
non è memorizzato nella stessa pagina sebbene abbia uno spazio di 256 byte (7680 b + 256 = 7936 che è ancora più piccolo di 8 KB), viene creata una nuova pagina di dati, ma quella nuova riga potrebbe adattarsi alla stessa vecchia pagina , perché SQL Server crea una nuova pagina quando è possibile risparmiare spazio e tempo di ricerca acquistandolo inserendolo nella pagina esistente?
Nota: sta succedendo la stessa cosa nell'indice heap.