34,575
社区成员
发帖
与我相关
我的任务
分享
use test;
go
if object_id('bigrows', 'U') is not null
drop table bigrows;
go
/*
测试设计
1.创建一个简单的表,两个字段即可,一个定长,一个变长,使之具有普遍性
2.第一个字段使用整形,并作为主键
3.第二个字段使用变长,取值1600字符,这样能用少量的记录行就能填充一个数据页
*/
create table bigrows
(
a int primary key,
b varchar(1600)
);
go
/*
记录长度计算
假设变长列全部占用
record-len = TagA + TagB + FSize + FData + Ncol + Nullbits
+ VarCount + VarOffset + VarData + RowOffset
= 1 + 1 + 2 + 4 + 2 + 1 + 2 + 2 + 1600 + 2
= 1617 byte
一个数据页可以容纳的记录行数
row-count = 8096 / 1617 ≈ 5
为了使得聚集索引还有插入的空间 a 使用等差数列 差为5 以5开头
*/
insert into bigrows
values(5, replicate('a', 1600));
insert into bigrows
values(10, replicate('b', 1600));
insert into bigrows
values(15, replicate('c', 1600));
insert into bigrows
values(20, replicate('d', 1600));
insert into bigrows
values(25, replicate('e', 1600));
--用dbcc ind命令查看数据页情况
dbcc ind(test, bigrows, -1)
go
/*
执行结果
PageFID PagePID IAMFID IAMPID IndexID PageType IndexLevel
------- ----------- ------ ----------- ----------- -------- ----------
1 78 NULL NULL 1 10 NULL
1 41 1 78 1 1 0
只显示了有用的列
得到聚集索引叶子层的一个数据页 1:41
*/
--查看数据页详细情况
dbcc traceon(3604);
go
dbcc page(test, 1, 41, 1);
go
/*
Row - Offset
4 (0x4) - 6556 (0x199c) ---a = 25
3 (0x3) - 4941 (0x134d) ---a = 20
2 (0x2) - 3326 (0xcfe) ---a = 15
1 (0x1) - 1711 (0x6af) ---a = 10
0 (0x0) - 96 (0x60) ---a = 5
*/
--插入第六行导致数据页拆分
insert into bigrows
values(7, replicate('x', 1600));
dbcc ind(test, bigrows, -1);
go
/*
得到 1:126
1:41
*/
--先查看原始分页的情况
dbcc page(test, 1, 41, 1);
go
/*
Row - Offset
2 (0x2) - 1711 (0x6af) a = 10
1 (0x1) - 3326 (0xcfe) a = 7
0 (0x0) - 96 (0x60) a = 5
*/
--在查看新分页
dbcc page(test, 1, 126, 1);
go
/*
Row - Offset
2 (0x2) - 3326 (0xcfe) a = 25
1 (0x1) - 1711 (0x6af) a = 20
0 (0x0) - 96 (0x60) a = 15
*/
/*
可以看出原始分页发生了拆分,前两行留在了原始分页
page 41,新记录 a = 7 这两行的中间
原始分页的后三行被移动到了新的分页 page = 126
*/
--改变插入的位置,重头来,插入 a = 22的记录
--得到的结果是前三行依然留在原始分页,后两行移动到新分页,新记录插在它们中间
--过程省略
--疑问:什么时候才能出现记录的前半段被移动到新页呢?