槽阵列和总页面大小

oou*_*ire 13 sql-server-2008 storage-engine data-pages database-internals

我继续在许多论坛和许多博客上看到一个页面的组成如下所示: 页面大小:16 x 512B = 8192B 页眉:= 96B 最大 In_Row 行:= 8060B

这留下 (8192 - 96 - 8060)B = 36B。

好的,这是合乎逻辑且正确的。我的问题是:为什么那么多人说剩下的36B是留给slot array的?

显然,插槽数组在页面上每行给出 2B;所以,它可以小到 2B,大到 1472B:

2B:1 行 * 2B = 2B

1472B:8096B = n*9B(带开销的最小行大小……想想单个 TINYINT 列)+ n*2B(每行槽阵列成本)=> 8096 = 11n => n = 8096 / 11 = 736。

736*2B = 1472B。

由于 14B 版本标签,这使我达到 20。

USE master ;
GO

CREATE DATABASE test ;
GO

USE test ;
GO

ALTER DATABASE test
    SET ALLOW_SNAPSHOT_ISOLATION ON ;
GO

ALTER DATABASE test
    SET READ_COMMITTED_SNAPSHOT ON ;
GO

DROP TABLE tbl ;
GO

CREATE TABLE tbl
(
      i CHAR(8000) DEFAULT(REPLICATE('a',8000))
    , j CHAR(53)   DEFAULT(REPLICATE('a',53))
) ;

INSERT INTO tbl 
    DEFAULT VALUES ;
GO

DBCC IND (test,tbl,-1) ;
GO
DBCC TRACEON(3604) ;
GO
DBCC PAGE(test,1,272,3) ;
GO
Run Code Online (Sandbox Code Playgroud)

另一个例子。如果从 49 转到 50,则 VARCHAR(MAX) 将转到 LOB_DATA。

DROP TABLE tbl ;
GO

CREATE TABLE tbl
(
      i VARCHAR(MAX) DEFAULT(REPLICATE('a',8000))
    , j CHAR(49)   DEFAULT(REPLICATE('a',49))
) ;

sp_tableoption N'tbl', 'large value types out of row', 'OFF' ;
GO

INSERT INTO tbl 
    DEFAULT VALUES ;
GO

DBCC IND (test,tbl,-1) ;
GO
DBCC TRACEON(3604) ;
GO
DBCC PAGE(test,1,272,3) ;
GO
Run Code Online (Sandbox Code Playgroud)

即使在 SQL Server 2012 中,这个问题似乎仍然存在。@SQLKiwi 指向 Kimberly Tripp 的这篇文章 - http://www.sqlskills.com/blogs/kimberly/a-simple-start-table-creation-best-practices / .

Pau*_*ite 8

如果页面用于排序运行等内部目的,则最大行大小为 8094 字节。对于数据页,包括内部行开销在内的最大行内大小为8060 字节

如果使用某些引擎功能,内部行开销会显着增加。例如,使用稀疏列将用户可访问的数据大小减少到 8019 字节。

我所知道的直到 SQL Server 2012 的外部行开销的唯一示例是版本化行所需的 14 个字节。这种外部开销使单行的最大空间使用量达到 8074 字节,加上单槽数组条目的 2 个字节,总共 8076 个字节。这仍然比 8096 限制(8192 页大小 - 96 字节固定标头)少 20 个字节。

最可能的解释是,原来的8060字节的限制留下34个字节为将来的扩展,它被用于行版本实现14。