6,129
社区成员
发帖
与我相关
我的任务
分享
/*----------------------------------------------------------------------
*auther:Poofly
*date:2010.3.14
*VERSION:
Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86)
Jul 9 2008 14:43:34
Copyright (c) 1988-2008 Microsoft Corporation
Enterprise Evaluation Edition on Windows NT 6.1 <X86> (Build 7600: )
*转载请注明出处
*更多精彩内容,请进http://blog.csdn.net/feixianxxx
------------------------------------------------------------------------*/
--建表(表源来自技术内幕)
GO
CREATE TABLE NC_JNodes (
id int NOT NULL ,
str1 char (5) NOT NULL ,
str2 varchar (10) NULL
);
GO
--在str2上建立唯一性的聚集索引,在str1上建立具有唯一性的非聚集索引
CREATE UNIQUE CLUSTERED INDEX idxcl_str2 on NC_JNodes (str2);
CREATE UNIQUE INDEX idxNC ON NC_JNodes (str1);
GO
--插入数据
DECLARE @i int;
SET @i = 1240;
WHILE @i < 13000 BEGIN
INSERT INTO NC_JNodes
SELECT @i, cast(@i AS char),
cast(cast(@i * rand() AS int) as char); --打乱了str1的排序
SET @i = @i + 1;
END;
GO
--查看页面分布和页号文件号
TRUNCATE TABLE sp_table_pages;
INSERT INTO sp_table_pages
EXEC ('dbcc ind (poofly,NC_JNodes, -1)');
SELECT PageFID, PagePID, IndexID, IndexLevel, PageType
FROM sp_table_pages
WHERE IndexLevel >= 0;
/*
PageFID PagePID IndexID IndexLevel PageType
------- ----------- ------- ---------- --------
5 967 1 0 1 --该条是聚集索引的叶级别的数据页面
5 969 2 0 2 --该条是非聚集索引的叶级别的索引页面
5 971 1 1 2 --该条是聚集索引的子结点的索引页面
5 972 1 0 1
5 973 2 1 2 --该条是非聚集索引的子结点的索引页面
5 974 2 0 2
5 975 1 0 1
*/
dbcc traceon(3604)
dbcc page(poofly,5,973,1)--非聚集索引的子结点的索引页面
/*
Slot 0, Offset 0x60, Length 12, DumpStyle BYTE
00000000: 06000000 1000c903 00000500 †8224 ?†8224 ?†8224 ?†8224 ?†8224 ?............
Slot 1, Offset 0x138, Length 12, DumpStyle BYTE
00000000: 06313036 33310304 00000500 †8224 ?†8224 ?†8224 ?†8224 ?†8224 ?.10631......
Slot 2, Offset 0x144, Length 12, DumpStyle BYTE
00000000: 06313132 34340404 00000500 †8224 ?†8224 ?†8224 ?†8224 ?†8224 ?.11244......
*/
--我们来看下第一个索引行
06->状态位A
000000 1000->无效的键值
c903 0000->Ox03c9==969 表示指向下一层的第一个非聚集索引页面号
0500->文件号
--接下来看第二个索引行
06->状态位A
313036 3331->'10631' 这个是str1 非聚集索引值,是下一层非聚集索引页的第一个值
0304 0000->Ox0403==1027 表示指向下一层的非聚集索引页面号
0500->文件号
--可以发现这个非聚集索引的结点行的结构好像跟聚集索引的结点行很像,第一行的所在键值都是无效的,只有从第二行开始有效
--我们来验证下这个假设吧
dbcc page(poofly,5,1027,1)
/*
Slot 0, Offset 0x60, Length 23, DumpStyle BYTE
00000000: 36313036 33310200 00010017 00363238 †10631.......628
00000010: 38202020 202020†8224 ?†8224 ?†8224 ?†8224 ?†8224 ?†8224 ?†8224 ?†8224 ?†8224 ?†8224 ?†8224 ?8
*/
注意看这里的第个到第个字节 3130363331='10631' 正好对应上我们在叶级别存储的那个非聚集值
这条记录下面的存储我在以前也说过了就是一般的拥有聚集索引的表的非聚集索引叶级别的存储了,不再多描述
--建表(表源技术内幕系列)
CREATE TABLE NC_NU_JNodes (
id int NOT NULL ,
str1 char (5) NOT NULL ,
str2 varchar (10) NULL
);
GO
--在str2建立
CREATE UNIQUE CLUSTERED INDEX idxcl_str2 on NC_NU_JNodes (str2);
CREATE INDEX idxNC ON NC_NU_JNodes (str1);
GO
SET NOCOUNT ON;
GO
DECLARE @i int;
SET @i = 1240;
WHILE @i < 13000 BEGIN
INSERT INTO NC_NU_JNodes
SELECT @i, cast(@i AS char),
cast(cast(@i * rand() AS int) as char); --打乱了str1的排序
SET @i = @i + 1;
END;
GO
--查看页面分布和页号文件号
TRUNCATE TABLE sp_table_pages;
INSERT INTO sp_table_pages
EXEC ('dbcc ind (poofly,NC_NU_JNodes, -1)');
SELECT PageFID, PagePID, IndexID, IndexLevel, PageType
FROM sp_table_pages
WHERE IndexLevel >= 0;
/*
PageFID PagePID IndexID IndexLevel PageType
------- ----------- ------- ---------- --------
5 1051 1 0 1
5 1053 2 0 2
5 1055 1 1 2
5 1104 1 0 1
5 1105 2 1 2
5 1106 2 0 2
5 1107 1 0 1
。。。。。
*/
dbcc traceon(3604)
dbcc page(poofly,5,1105,1)
/*
Slot 0, Offset 0x60, Length 12, DumpStyle BYTE
00000000: 06066161 de001d04 00000500 †8224 ?†8224 ?†8224 ?†8224 ?†8224 ?..aa.......
Slot 1, Offset 0x259, Length 29, DumpStyle BYTE
00000000: 36313036 33318304 00000500 02000001 †10631..........
00000010: 001d0037 37393920 20202020 20†8224 ?†8224 ?†8224 ?†8224 ?...7799
Slot 2, Offset 0x276, Length 29, DumpStyle BYTE
00000000: 36313133 30318404 00000500 02000001 †11301..........
00000010: 001d0031 30303832 20202020 20†8224 ?†8224 ?†8224 ?†8224 ?...10082
*/
--让我们来分析下索引行的第一行
06->状态位A
066161 de00->无效的键值
1d04 0000->Ox041d==1053 表示指向下一层的第一个非聚集索引页面号
0500->文件号
--第二条索引行
36->状态位A
313036 3331->=='10631'这个是str1 非聚集索引值,是下一层非聚集索引页的第一个值
8304 0000->Ox0483==1155 表示指向下一层的第一个非聚集索引页面号
0500->==5 文件号
0200->==2该页上的列数
00->NULL位图
0100->==1变长列的数目
1d00->00011101=13+16=29 第一列变长列的结束位置即该索引行的长度
37 37393920 20202020 20->=='7799 '聚集键值
--验证下:
dbcc page(poofly,5,1155,3)--STYLE 3 可以以表格形式显示一些信息
/*
FileId PageId Row Level str1 (key) str2 (key) KeyHashValue
------ ----------- ------ ------ ---------- ---------- ----------------
5 1155 0 0 10631 7799 (f90044db974c)
5 1155 1 0 10641 3241 (f500488c99d3)
5 1155 2 0 10644 8469 (fd006debfe58)
....
*/
看这里的第一条 str1='10631' str2='7799' 就是上面非聚集索引非叶级别的第二条索引行读出的值