SQL Server存储内幕之三:heap结构

源文档 <http://www.sqlservercentral.com/blogs/livingforsqlserver/archive/2010/12/19/sql-server-storage-internals-part-3-architecture-of-heap-structure.aspx>

在前面两部分我们介绍了基础知识和分区的一些概念,本部分我们介绍以下主题:

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页如何用于查找表的正确盘区

3_4_Heap_Query.jpg
小结:

本节我们介绍了heap表的创建以及如何查看分配页面信息和heap结构中IAM的角色,同时也了解了在heap表中,其页面彼此没有任何的链接关系。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/355374/viewspace-683205/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/355374/viewspace-683205/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值