-- Exemplo 1: com índice agrupado
CREATE TABLE tbl5
(
i VARCHAR(900) NOT NULL
) ;
GO
CREATE CLUSTERED INDEX CIX_tbl5
ON tbl5 (i ASC) ;
GO
INSERT INTO tbl5
( i )
VALUES
( REPLICATE('a' , 900) )
, ( REPLICATE('b' , 900) )
, ( REPLICATE('c' , 900) )
, ( REPLICATE('d' , 900) )
, ( REPLICATE('e' , 900) )
, ( REPLICATE('f' , 900) )
, ( REPLICATE('g' , 900) )
, ( REPLICATE('h' , 900) ) -- 900 x 8 + (13 x 8) = 7200 + 104 = 7304
, ( REPLICATE('i' , 761) ) ;-- 7304 + 761 + 13
GO -- = 8078 + 96(Page Header) + 18 (Slot)
-- = 8192
-- m_freeCnt = 0
DBCC IND(tempdb,tbl5,-1) ; -- everything is IN_ROW_DATA
GO
DBCC TRACEON(3604) ;
GO
DBCC PAGE(tempdb,1,177,3) ;
GO
-- Exemplo 2: Com heap. Quando a coluna 'i' é 392 m_freeCnt = 387. Quando 'i' = 393, obtenho uma nova página. Por que não posso adicionar mais bytes a 'i'?
CREATE TABLE tbl6
(
i VARCHAR(900) NOT NULL
) ;
GO
INSERT INTO tbl6
( i )
VALUES
( REPLICATE('a' , 900) )
, ( REPLICATE('b' , 900) )
, ( REPLICATE('c' , 900) )
, ( REPLICATE('d' , 900) )
, ( REPLICATE('e' , 900) )
, ( REPLICATE('f' , 900) )
, ( REPLICATE('g' , 900) )
, ( REPLICATE('h' , 900) )
, ( REPLICATE('i' , 393) ) ;
GO
DBCC IND(tempdb,tbl6,-1);
GO
DBCC TRACEON(3604);
GO
DBCC PAGE(tempdb,1,181,3);
GO
'page split' e 'heap' não devem ser usados na mesma frase. Você quer dizer por que a linha de tamanho 393+change não coube no espaço livre da primeira página da pilha? Isso ocorre porque as informações de espaço livre do PFS não têm resolução alta o suficiente, consulte Gerenciando alocações de extensão e espaço livre :
Caberia na página, de fato, mas o PFS apenas diz que a página é '95_PCT_FULL' e o registro inserido é razoavelmente grande e próximo ao espaço livre conforme o PFS (95% de 8060 é 403), então o INSERT escolhe para alocar uma nova página.
Com um B-Tree, a posição do registro é determinística devido à ordem das chaves, portanto, o mecanismo deve carregar a página e verificar o espaço livre, e o registro caberá.