在前面两部分我们介绍了基础知识和分区的一些概念,本部分我们介绍以下主题:
1)heap表的知识点
2)表被创建时发生了什么?
3)如何显示heap表的IAM和数据页清单
由于所有数据页、索引页和系统页以16进制的格式存储,补充一下16进制到10进制的转换知识显得尤为重要。
下表是16进制和10进制的对照图:
16进制 10进制
A 10
F 15
10 16
FF 255
heap结构:
1. heap表是没有聚集索引的表
2. IAM用于查找分配给heap的所有数据页信息
3. 对于大多数较小的heap表来说,仅需要一个IAM页就可以管理其页面。
4. 若heap表大于4GB或包含LOB数据类型的话,则会包含多个IAM页面。
5. 当查询要获取heap表的所有记录时,SQL Server使用IAM页来扫描heap表
6. 与聚集索引或非非聚集索引不同,heap内的页面没有任何链接,也就是说所有heap页面的header头中的m_prevPage和m_nextPage值都是0:0。
当创建一个未建聚集索引的表时,从sys.indexes表可以根据index_id为0的行可以找到表的详细信息。
Index_id in sys.indexes Meaning
0 Heap
1 Clustered Index
>1 Non Clustered Index
以下查询输出数据库的所有heap表信息:
select OBJECT_NAME(object_id), index_id, type_desc
from sys.indexes
where index_id = 0
要更好的理解heap表结构,接下来我们来创建tExample3的示例表:
CREATE TABLE tExample3(
strEmplCode int identity(1001,1),
strFirstName varchar(100),
strDeptCode char(6) NOT NULL,
strAddress varchar(500),
intSalary int)
GO
注意:
当新建表时,默认并不会给表分配页面,只有新插入记录时,会从混合盘区中为表分配一个页面,随着表的增长,会使用统一盘区进行分配。
以下查询显示表的页面初始分配情况:
select so.name, so.object_id, sp.index_id, internals.total_pages, internals.used_pages, internals.data_pages, first_iam_page, first_page, root_page
from sys.objects so
inner join sys.partitions sp on so.object_id = sp.object_id
inner join sys.allocation_units sa on sa.container_id = sp.hobt_id
inner join sys.system_internals_allocation_units internals on internals.container_id = sa.container_id
where so.object_id = object_id('tExample3')
go
name object_id index_id total_pages used_pages data_pages first_iam_page first_page root_page
tExample3 341576255 0 0 0 0 0x000000000000 0x000000000000 0x000000000000
说明:
index_id: 由于表是heap所以为0
Total_pages: 由于表是空表,所以页数为0
First_iam_page和first_page: 由于未分配页给heap,所以页面地址均为0
Root_page: 仅适用于索引结构
现在往heap表插入1000条记录,然后分析空间分配情况:
INSERT INTO tExample3(strFirstName, strDeptCode, strAddress, intSalary)
VALUES('AAAAA', 'DEPT01', 'CHENNAI', '12500')
GO 1000
接下来运行以下查询查看其空间分配情况:
select so.name, so.object_id, sp.index_id, internals.total_pages, internals.used_pages, internals.data_pages, first_iam_page, first_page, root_page
from sys.objects so
inner join sys.partitions sp on so.object_id = sp.object_id
inner join sys.allocation_units sa on sa.container_id = sp.hobt_id
inner join sys.system_internals_allocation_units internals on internals.container_id = sa.container_id
where so.object_id = object_id('tExample3')
go
输出:
name object_id index_id total_pages used_pages data_pages first_iam_page first_page root_page
tExample3 341576255 0 7 7 6 0x020100000100 0x010100000100 0x000000000000
说明:
index_id: 由于表是heap所以为0
Total_pages: 分配了7个页面(1个IAM页和6个数据页)
First_iam_page:IAM页面地址为0x020100000100
First_page: 数据页面的地址为0x010100000100
Root_page: 仅适用于索引结构
注意到first_iam_page和first_page的值以16进制格式存储,下面我们会逐一分解:
首先分解first_iam_page
第一步: 每2个字节进行分组显示
0x 02 01 00 00 01 00
第二步: 从右至左读取
0x 02 01 00 00 01 00
变成
0x 00 01 00 00 01 02
第三步: 前两字节表示文件组号,剩余4个字节表示页号
文件组号以16进制表示: 00 01,其10进制表示为1
页号16进制表示: 00 00 01 02,其10进制表示为258
最终heap的第一个页号为: 1:258
当然也可以使用以下的命令来获取heap表的所有页面信息:
DBCC TRACEON(3604)
DBCC IND('LearningInternals', 'tExample3', -1)
DBCC TRACEOFF(3604)
输出:
PageFID PagePID IAMFID IAMPID ObjectID IndexID PartitionNumber PartitionID iam_chain_type PageType IndexLevel NextPageFID NextPagePID PrevPageFID PrevPagePID
1 258 NULL NULL 341576255 0 1 72057594039304192 In-row data 10 NULL 0 0 0 0
1 257 1 258 341576255 0 1 72057594039304192 In-row data 1 0 0 0 0 0
1 259 1 258 341576255 0 1 72057594039304192 In-row data 1 0 0 0 0 0
1 260 1 258 341576255 0 1 72057594039304192 In-row data 1 0 0 0 0 0
1 261 1 258 341576255 0 1 72057594039304192 In-row data 1 0 0 0 0 0
1 262 1 258 341576255 0 1 72057594039304192 In-row data 1 0 0 0 0 0
1 263 1 258 341576255 0 1 72057594039304192 In-row data 1 0 0 0 0 0
tExample3 表的IAM页是: (1: 258),其数据页分别为: (1:257),(1:259),(1:260),(1:261),(1:262),(1:263)
以下图描述了SQL Server数据库引擎如何使用IAM页面获取数据行
注意:此图仅描述IAM页如何用于查找表的正确盘区
小结:
本节我们介绍了heap表的创建以及如何查看分配页面信息和heap结构中IAM的角色,同时也了解了在heap表中,其页面彼此没有任何的链接关系。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/355374/viewspace-683205/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/355374/viewspace-683205/