SQL Server存储数据的基本单元是Page,每一个Page的大小是8KB,数据文件是由Page构成的。在同一个数据库上,每一个Page都有一个唯一的资源标识,标识符由三部分组成:db_id,file_id,page_id,例如,15:1:8733,15是数据库的ID,1是数据文件的ID,8733是Page的编号,Page的编号从0依次递增。8个连续的Page组成一个区(Extent),数据文件中已分配(Allocated)的空间被分割成区的整数倍。一次磁盘IO操作作用于Page级别,而空间分配的最小单元是区。

一,Page的类型

Page是用于存储数据的,不同类型的Page存储的数据是不同的,Page的结构也是不同的。有些Page是用于存储数据的,叫做Data Page,有些Page是用于存储索引结构中的中间节点的,叫做Index Page,有些Page是SQL Server存储引擎使用的,用于管理Page的,叫做系统页。Page类型和存储的数据类型如下表所示:

Page type Contents
Data Data rows with all data, except text, ntext, image, nvarchar(max), varchar(max), varbinary(max), and xml data, when text in row is set to ON.
Index Index entries.
Text/Image Large object data types: (text, ntext, image, nvarchar(max), varchar(max), varbinary(max), and xml data)
Variable length columns when the data row exceeds 8 KB: (varchar, nvarchar, varbinary, and sql_variant)
Global Allocation Map, Shared Global Allocation Map Information about whether extents are allocated.
Page Free Space (PFS) Information about page allocation and free space available on pages.
Index Allocation Map Information about extents used by a table or index per allocation unit.
Bulk Changed Map Information about extents modified by bulk operations since the last BACKUP LOG statement per allocation unit.
Differential Changed Map Information about extents that have changed since the last BACKUP DATABASE statement per allocation unit.

日志文件没有Page结构,它是由一系列的日志记录构成的。本文关注的是Data Page和Index Page,跟数据表有关。

二,数据Page的结构

每一个Page都由头部(Header),内容(Content)和行偏移量(Offset)组成,也叫做Slot,头部是在Page的开始处,占用96Bytes,用于存储Page的编号,Page的类型,分配单元(Allocation Unit)等系统信息。注:在单个Page中最多存储8060Bytes的数据,也就是一行要想存储到一个Page中,该行包含的字节最大不能超过8060Bytes,超过8060Bytes的行会被拆分。

数据行存储在Page Header之后,数据行在Page中的物理存储是无序的,行的逻辑顺序是由行偏移(Row Offset)确定的,行偏移存储在Page的末尾,每一个行偏移是一个Slot,占用2B。行偏移连续排列在Page的末尾,称作槽数组(Slot Array)。行偏移以倒序方式存储行的偏移量,这意味着,从Page末尾向Page 开头计数,第一行的偏移量存储在Page的末尾Slot中,第二行的偏移量存储在Page末尾的第二个Slot中。

三,DBCC PAGE()命令

PAGE中存储的数据页或索引页,可以使用非正式的命令来查看:

DBCC PAGE(['database name'|database id], file_id, page_number, print_option = [0|1|2|3] )

参数注释:

  • database_id:page所在的数据库
  • file_id:数据库文件的ID;
  • page_number:该Page在文件中的编号;
  • print_option是指打印信息的详细程度,默认值是0,只打印Page Header。

参数Print_option的有效值是0、1、2、3,表示显示信息的详细程度:

  • 0 – print just the page header
  • 1 – page header plus per-row hex dumps and a dump of the page slot array (unless its a page that doesn’t have one, like allocation bitmaps)
  • 2 – page header plus whole page hex dump
  • 3 – page header plus detailed per-row interpretation

四,查看Page头部信息

Page头部信息存储的是Page的系统信息,例如,查看资源标识符:15:1:8777733 Page的头部信息:

dbcc traceon(3604)
dbcc page(15,1,8777733)

在我的数据库中,该Page的头部信息(移除Buffer的数据)如下所示,

PAGE: (1:8777733)

PAGE HEADER:
Page @0x0000005188B02000 m_pageId = (1:8777733) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x220
m_objId (AllocUnitId.idObj) = 28503 m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057595905900544
Metadata: PartitionId = 72057594059423744 Metadata: IndexId = 1
Metadata: ObjectId = 1029578706 m_prevPage = (1:8777732) m_nextPage = (1:8777734)
pminlen = 16 m_slotCnt = 2 m_freeCnt = 4513
m_freeData = 3675 m_reservedCnt = 0 m_lsn = (1212327:16:558)
m_xactReserved = 0 m_xdesId = (0:799026688) m_ghostRecCnt = 0
m_tornBits = -1518328013 DB Frag ID = 1 Allocation Status
GAM (1:8690944) = ALLOCATED SGAM (1:8690945) = NOT ALLOCATED
PFS (1:8775480) = 0x40 ALLOCATED 0_PCT_FULL DIFF (1:8690950) = CHANGED
ML (1:8690951) = NOT MIN_LOGGED  

Page 头部返回的各个字段的含义:

1,Page的编号

m_pageId = (1:8777733),该Page所在的File ID 和Page ID

2,Page的类型

m_type = 1,Page的类型,常见的类型是数据页和索引页:

  • 1 – data page,用于表示:堆表或聚集索引的叶子节点
  • 2 – index page,用于表示:聚集索引的中间节点或者非聚集索引中所有级别的节点

其他Page类型(系统页是管理Page的Page,例如,GAM,IAM等)如下

  • 3 – text mix page,4 – text tree page,用于存储类型为文本的大对象数据
  • 7 – sort page,用于存储排序操作的中间数据结果
  • 8 – GAM page,用于存储全局分配映射数据GAM(Global Allocation Map),每一个数据文件被分割成4GB的空间块(Chunk),每一个Chunk都对应一个GAM数据页,GAM数据页出现在数据文件特定的位置处,一个bit映射当前Chunk中的一个区。
  • 9 – SGAM page,用于存储SGAM页(Shared GAM)
  • 10 – IAM page,用于存储IAM页(Index Allocation Map)
  • 11 – PFS page,用于存储PFS页(Page Free Space)
  • 13 – boot page,用于存储数据库的信息,只有一个Page,Page的标识符是:db_id:1:9,
  • 15 – file header page,存储数据文件的数据,数据库的每一个文件都有一个,Page的编号是0。
  • 16 – diff map page,存储差异备份的映射,表示从上一次完整备份之后,该区的数据是否修改过。
  • 17 – ML map page,表示从上一次备份之后,在大容量日志(bulk-Logged)操作期间,该区的数据是否被修改过,This is what allows you to switch to bulk-logged mode for bulk-loads and index rebuilds without worrying about breaking a backup chain.
  • 18 – a page that’s be deallocated by DBCC CHECKDB during a repair operation.
  • 19 – the temporary page that ALTER INDEX … REORGANIZE (or DBCC INDEXDEFRAG) uses when working on an index.
  • 20 – a page pre-allocated as part of a bulk load operation, which will eventually be formatted as a ‘real’ page.

3,Page在索引中的级数

数据页在索引中的索引级数,m_level=0,表示处于Leaf Level。

  • 对于堆表(Heap),m_level=0表示的是Data Page;
  • 对于聚集索引,m_level=0表示的是Data Page;
  • 对于非聚集索引,m_level=0表示的是叶子节点

4, Page的元数据

Page的元数据十分重要,不仅能够查看处Page所在的Object,甚至能够查看该Page所在的分配单元和分区ID,在死锁进行故障排除时十分有用

  • Metadata: AllocUnitId =72057595905900544,该Page所在的分配单元ID(allocation_unit_id)
  • Metadata: PartitionId =72057594059423744,该Page所在的分区的分区ID(partition_id)
  • Metadata: IndexId = 1,该Page所在的索引ID
  • Metadata: ObjectId = 1029578706,用于表示Page所属对象的object_id

5,page的链指针

由于数据表的Page并不是单独存在的,而是通过双向链式结构连接在一起的,

  • m_prevPage = (1:8777732)       :用于表示前一个page (FileID : PageID)
  • m_nextPage = (1:8777734)  :用于表示下一个page (FileID:PageID)

6, 其他头部字段  

  • m_slotCnt = 2            :页面中Slot的数量,用于Page中存储的数据行数
  • m_freeCnt = 4513   :页面中剩余的空间,单位是字节,还剩83字节的空间 
  • m_reservedCnt = 0    :为活动事务保留的存储空间,单位是字节
  • m_ghostRecCnt = 0   :页面中存在的幽灵记录的总数(ghost record count)

关于Page头部的信息,可以阅读《Inside the Storage Engine: Anatomy of a page》;

五,利用Page的元数据排除死锁

Page的元数据包含分区ID,索引ID和对象ID,用户可以使用这些元数据,分析死锁产生的原因。系统追踪到产生死锁的资源,可能是一个Page的资源标识符,如果能够确认发生死锁是由于数据表或索引的分区不合理导致的,那么可以重新设置分区列,或者设置分区边界值,把单个分区拆分成多个分区,这样就能把竞争的临界资源分配到不同的分区中,避免查询请求对资源的竞争,进而减少死锁的发生。

  • Metadata: PartitionId ,该Page所在的分区的分区ID(partition_id);
  • Metadata: IndexId ,该Page所在索引ID;
  • Metadata: ObjectId,用于表示对象的object_id;

参考文档:

Pages and Extents Architecture Guide

Using DBCC PAGE to Examine SQL Server Table and Index Data

Inside the Storage Engine: How are allocation unit IDs calculated?

Inside the Storage Engine: Anatomy of a page

笔记17 DBCC IND()非常详细解释加dbcc page([GPOSDB],1,119,3)非常详细解释 2013-1-20

查看Page结构的更多相关文章

  1. Page结构

    SQL Server存储数据的基本单元是Page,每一个Page的大小是8KB,数据文件是由Page构成的.在同一个数据库上,每一个Page都有一个唯一的资源标识,标识符由三部分组成:db_id,fi ...

  2. SOME:收缩数据库日志文件,查看表数据量和空间占用,查看表结构索引修改时间

    ---收缩数据库日志文件 USE [master]ALTER DATABASE yourdatabasename SET RECOVERY SIMPLE WITH NO_WAITALTER DATAB ...

  3. sp_help 快速查看表结构、视图信息

    sp_helptext: 是MS SQL Server的一个系统存储过程,可以通过它来查看存储过程或者视图.函数源码 示例:sp_helptext viewName (viewName  即要查询的存 ...

  4. Sql语句查看表结构

    快速查看表对的就说明,及表字段描述及字段类型 --表描述 SELECT tbs.name 表名,ds.value 描述 FROM sys.extended_properties ds LEFT JOI ...

  5. MySQL 查看表结构

    mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名; use information_s ...

  6. mysql查看表结构命令

    mysql查看表结构命令 mysql查看表结构命令,如下: desc 表名;show columns from 表名;describe 表名;show create table 表名; use inf ...

  7. 查看表结构命令(mysql和oracle)

    MySQL查看表结构SQL语句 = mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名; ...

  8. mysql查看表结构2种方式对比

    1.desc t_bookType; 2.show create table t_bookType; 相信大部分人还是喜欢第一种查看表结构方式.

  9. SQL Server--------SQL Server常用(查看注释,新增注释,生成实体,查看表结构信息,case when...)

    --新增字段: ALTER TABLE line_info ADD line_remark NVARCHAR(MAX) DEFAULT ''  EXECUTE sp_addextendedproper ...

随机推荐

  1. 张高兴的 Windows 10 IoT 开发笔记:DHT11 温湿度传感器

    GitHub : https://github.com/ZhangGaoxing/windows-iot-demo/tree/master/DHT11Demo

  2. UVa816,Ordering Tasks,WA

    #include <iostream> #include <cstdio> #include <string> #include <cstring> # ...

  3. kettle系列一之eclipse开发

    1.引言 最近公司开始一个etl项目,底层结合开源的kettle进行开发.那么学习kettle势在必行,kettle的使用在这里就不用介绍了,网上有很多的资料.例如:kettle中文社区,我们在这里主 ...

  4. Fedora 19 搭建Qt环境

    1.搭建桌面环境fedora的源里包含的需要的套件包,用下面命令安装sudo yum intall qt qt-devel qt-x11 qt-doc qt-demos qt-examples qt- ...

  5. *.do和*.action的区别

    最近发现个问题,都是SpringMVC 请求地址有的是*.do有的是*.action,想了半天区别没想出来. struts早期的1版本,以.do为后缀.同时spring的MVC也是以.do为后缀.几年 ...

  6. 解决phpstorm ftp自动保存文件问题

    初次使用phpstorm, 1.配置ftp时,远程文件要用/ftp用户名/文件夹名: 2.由于版本管理的原因(猜测),直接从本地原有文件修改时各种办法都无法上传,结果从服务器上下载一份再修改,解决这个 ...

  7. Java web学习 Cookie&&Session

    cookie&&session 会话技术 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话.会 话技术就是记录这次会话中客户端的状态与数据的. 会话技术分为Coo ...

  8. JAVA提高十一:LinkedList深入分析

    上一节,我们学习了ArrayList 类,本节我们来学习一下LinkedList,LinkedList相对ArrayList而言其使用频率并不是很高,因为其访问元素的性能相对于ArrayList而言比 ...

  9. hadoop2集群中关键配置文件的记录

    配置HDFS  高可用 1.配置HDFS配置文件 $ vi hdfs-site.xml #写入 <configuration> #配置NameService 名字随便起 <prope ...

  10. LINUX环境下SVN安装与配置(利用钩子同步开发环境与测试环境)

    安装采用YUM一键安装: 1.环境Centos 6.6 2.安装svnyum -y install subversion 3.配置 建立版本库目录mkdir /www/svndata svnserve ...