TinyInt 的 SQL SERVER 存储

oou*_*ire 12 sql-server-2008

在 SQL Server 中,为什么一个 tinyint 以 9B 存储在行中。出于某种原因,在 NULL 位图掩码的末尾似乎还有一个额外的字节。

    使用临时数据库;
    走

    创建表 tbl
    (
        我 TINYINT 不为空
    );
    走

    插入 tbl (i)
        值 (1) ;
    走

    DBCC IND ('tempdb','tbl',-1) ;
    走

    DBCC TRACEON (3604) ; -- 页面转储将进入控制台
    走

    DBCC 页面 ('tempdb',1,168,3);
    走

结果(由于 DBCC PAGE 首先显示最低有效字节,因此我颠倒了字节):

Record Size = 9B
10000500 01010000 00
TagA = 0x10 = 1B
TagB = 0x00 = 1B
Null Bitmap Offset = 0x0005 = 2B
Our integer column = 0x01 = 1B
Column Count = 0x0001 = 2B
NULL Bitmap = 0x0000 = 2B (what!?)
Run Code Online (Sandbox Code Playgroud)

Rem*_*anu 13

如果您使用简单的大小加法计算记录,您确实会得到 8:4+1+2+1(标题+固定大小+空位图计数+空位图本身)。但是堆记录不能小于转发存根大小,即 9 字节,因为该记录必须保证它可以被转发存根替换。因此,该记录实际上将占用 9 个字节。smallint通过计算和最小大小,A将是 9 个字节。任何更大的都已经大于转发存根,因此您的计算大小与记录大小相匹配。


Aar*_*and 6

很高兴听到作者的耳朵。:-) Kalen 怀疑这只是强制执行某种最小行长度,其中任何 < 9 都被填充到 9。当然,只有少数情况是可能的。您会发现 TINYINT 和 BIT 以及 VARCHAR(1)/CHAR(1) 的幻像字节。如果您移动到 ​​SMALLINT 或 CHAR(2),它不会增加超过 9,但如果您移动到 ​​CHAR(3),它会增加。

因此,本质上您可以指出通过明智地选择数据类型可以获得的效率,但要指出在某些边缘情况下,由于存储层的其他因素,规则不适用。

编辑我确实希望为您提供更具体的信息。只是想让您知道,这就是 Internals 书的作者目前的想法。她不是100%确定。