为什么我的堆没有完全填满它的页面,而相同的聚集索引可以填满 m_freeCnt = 0?

oou*_*ire 4 sql-server-2008 storage-engine

-- 示例 1:使用聚集索引

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
Run Code Online (Sandbox Code Playgroud)

-- 示例 2:使用堆。当“i”列是 392 m_freeCnt = 387 时。当“i” = 393 时,我得到一个新页面。为什么我不能向“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
Run Code Online (Sandbox Code Playgroud)

Rem*_*anu 6

'page split' 和 'heap' 不应该用在同一个句子中。您的意思是为什么大小为 393+change 的行不适合堆第一页的可用空间?那是因为 PFS 可用空间信息的分辨率不够高,请参阅管理范围分配和可用空间:

PFS 为每一页分配一个字节,记录该页是否已分配,如果是,则记录该页是否为空、1% 至 50% 已满、51% 至 80% 已满、81% 至 95% 已满或 96% 至 100% 已满。

确实适合页面,但 PFS 只说页面是“95_PCT_FULL”,插入的记录相当大,接近 PFS 的可用空间(8060 的 95% 是 403),因此 INSERT 选择分配一个新页面。

对于 B 树,由于键顺序,记录位置是确定性的,因此引擎必须加载页面并检查可用空间,并且记录将适合。

  • 请注意,如果将大小减小到 392 个字符,结果记录(适合且不会导致“拆分”)的长度 *正好 * 403 个字节,即。95% 标记。393越过门槛。 (2认同)