第八周翻译

数据页和数据行
数据库中的空间被划分为逻辑的8KB页。这些页面从零开始连续编号,它们可以通过指定文件ID和页码来引用。页面编号始终是连续的,因此当SQLServer增长数据库文件时,新页将从文件中的最高页码加上一个页码开始编号。类似地,当SQLServer缩小文件时,它会从文件中移除编号最高的页.
SQL服务器中的数据存储
一般来说,SQL Server有三种不同的方式或技术来存储和处理数据库中的数据。对于传统的基于行的存储,数据存储在数据行中,数据行将来自所有列的数据组合在一起。
SQL Server2012引入了列存储索引和基于列的存储。这种技术将数据存储在每列而不是每一行的基础上。我们将在本书的第七部分中讨论基于列的存储。
最后是在SQL Server 2014中引入并进一步改进了SQL Server 2016中的内存存储技术。尽管它们为了冗余目的将数据保存在磁盘上,但它们的存储格式与基于行和列的存储非常不同。我们将在本书的第八部分讨论内存中的技术。
本书的这一部分主要讨论基于行的存储以及经典的B树索引和堆。
图1-6.数据页结构
图1-6.数据页结构
96字节的页眉包含有关页面的各种信息,例如页面所属的对象、页面上可用的行数和可用空间的大小,如果页面位于索引页链中,则链接到前页和下一页,等等。
在页眉后面是存储实际数据的区域。然后是自由空间。最后,有一个槽数组,它是一个由两个字节的条目组成的块,指示相应的数据在页面上开始的偏移量,槽数组表示页面上数据行的逻辑顺序。
如果页上的数据需要按索引键的顺序排列,则SQLServer不对页上的数据行进行物理排序,而是根据索引排序顺序填充槽数组。槽0(图1-6中最右边)存储数据行的偏移量,其键值在页面上最低;槽1,第二个最低键值;等等。
我们将在下一章中更深入地讨论索引。
让我们看看数据行的结构,如图1-7所示。
图1-7数据行结构
行的前两个字节,称为状态位A和状态位B,是包含有关行的信息的位图,如行类型,如果该行已在逻辑上被删除(幽灵),如果该行具有NULLvalue,则为可变长度列,和版本控制标签。
行中接下来的两个字节用于存储数据的固定长度部分的长度。
在固定长度数据部分之后,有一个空位图,其中包含两个不同的数据元素。前两个字节元素是行中的列数。第二个是空位图数组。这个数组对表的每个列都使用一个位,不管它是否为空。
空位图总是出现在堆表或聚集索引叶行中的数据行中,即使该表没有空列。但是,如果索引中没有可空列,则空位图不存在于非叶索引行或非聚集索引的叶级行中。
注 :我们将在第6章中讨论索引维护,在第9章中讨论触发器,在第21章中讨论乐观隔离级别。
让我们创建一个表,用一些数据填充它,并查看实际的行数据。代码显示在列表1-4中。复制函数将作为第一个参数提供的字符重复10次。
数据行格式:表格创建
create table dbo.DataRows
(
ID int not null,
Col1 varchar(255) null,
Col2 varchar(255) null,
Col3 varchar(255) null
);
insert into dbo.DataRows(ID, Col1, Col3) values (1,replicate(‘a’,10),replicate(‘c’,10));
insert into dbo.DataRows(ID, Col2) values (2,replicate(‘b’,10));
dbcc ind
(
‘SQLServerInternals’ /Database Name/
,‘dbo.DataRows’ /Table Name/
,-1 /Display information for all pages of all indexes/
);
一个无文档但众所周知的DBCCInd命令返回有关表页分配的信息。您可以在图1-8中看到此命令的输出。
图1-8.DBCCIND输出
这里有有两个属于表的页面,第一个页面类型=10,是一种称为IAM分配映射的特殊类型的页面。此页跟踪属于特定对象的页。但是,现在不要关注这个问题,因为我们将在本章后面讨论分配地图页。
注:SQL Server 2012引入了另一个无文档的数据管理函数(DMF),sys.dm_db_database_page_properties,可用作DBCCIND命令的替代。与DBCCIND相比,此DMF的输出提供了更多信息,并且可以将其与其他系统DMV和/或目录视图连接起来。
页面类型=1是包含数据行的实际数据页。PageFID和PagePID列显示页面的实际文件和页码。您可以使用另一个undocumented命令DBCC页面来检查它的内容,如清单1-5所示。
清单1-5数据行格式:DBCC页面调用-将DBCC页面输出重定向到控制台
dbcc traceon(3604);
dbcc page
(
‘SqlServerInternals’ /Database Name/
,1 /File ID/
,214643 /Page ID/
,3 /*Output mode: 3 - display page header and row details */
);
清单1-6显示了对应于第一个数据行的DBCC页的输出。SQL Server存储
按字节交换顺序的数据。例如,两个字节的值0001将存储为0100。
清单1-6。第一行的DBCC页输出
Slot 0 Offset 0x60 Length 39
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 39
Memory Dump @0x000000000EABA060
0000000000000000: 30000800 01000000 04000403 001d001d 00270061 0…’.a
0000000000000014: 61616161 61616161 61636363 63636363 636363 aaaaaaaaacccccccccc
Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4
ID = 1
Slot 0 Column 2 Offset 0x13 Length 10 Length (physical) 10
Col1 = aaaaaaaaaa
Slot 0 Column 3 Offset 0x0 Length 0 Length (physical) 0
Col2 = [NULL]
Slot 0 Column 4 Offset 0x1d Length 10 Length (physical) 10
Col3 = cccccccccc
让我们更详细地查看数据行,如图1-9所示。
图1-9第一数据行
如你所见,行以两个状态位开头,后跟一个双字节值0800。这就是
字节交换值0008,这是行中“列数”属性的偏移量。此偏移量
告诉SQL Server行的固定长度数据部分的结束位置。
接下来的四个字节用于存储固定长度的数据,在我们的例子中是id列。之后,有两个字节的值表示数据行有四列,后跟一个一字节的空值位图。只需四列,位图中的一个字节就足够了。存储值04,即00000100二进制格式。它指示行中的第三列包含空值。接下来的两个字节存储行中可变长度列的数量,即3(字节为0300-交换订单)。后面是一个偏移数组,其中每两个字节存储一个偏移量,其中变量-长度列数据结束。如你所见,即使col2为空,它仍然使用偏移数组中的槽。最后,还有来自可变长度列的实际数据。
现在,让我们看看第二个数据行。清单1-7显示了DBCC页面输出,图1-10显示了行数据。
图1-10 第二数据行数据
清单1-7第二行的DBCC页输出
Slot 1 Offset 0x87 Length 27
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 27
Memory Dump @0x000000000EABA087
0000000000000000: 30000800 02000000 04000a02 0011001b 00626262 0…bbb
0000000000000014: 62626262 626262 bbbbbbb
Slot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4
ID = 2
Slot 1 Column 2 Offset 0x0 Length 0 Length (physical) 0
Col1 = [NULL]
Slot 1 Column 3 Offset 0x11 Length 10 Length (physical) 10
Col2 = bbbbbbbbbb
Slot 1 Column 4 Offset 0x0 Length 0 Length (physical) 0
Col3 = [NULL]
第二行中的空位图表示一个二进制值000001010,它显示第1列和COL3为空。尽管该表有三个可变长度的列,但可变长度的数目行中的列表示偏移数组中只有两个列/槽。SQL Server没有维护行中有关尾随的空变长列的信息。
提示:通过以可变长度的方式创建表,可以减小数据行的大小。通常存储空值的列被定义为CREATETABLE语句中的最后一列。这是唯一一种情CREATETABLE语句中的列顺序很重要。
固定长度的数据和内部属性必须适合单个数据页上可用的8060字节。当情况并非如此时,SQL Server不允许您创建表。例如,清单1-8中的代码产生错误。
清单1-8。创建数据行大小超过8060字节的表
create table dbo.BadTable
(
Col1 char(4000),
Col2 char(4060)
)
Msg 1701, Level 16, State 1, Line 1
Creating or altering table ‘BadTable’ failed because the minimum row size would be 8,067,
including 7 bytes of internal overhead. This exceeds the maximum allowable table row size of
8,060 bytes.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值