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. JS中apply和call的区别和用法

    Javascript中有一个call和apply方法,其作用基本相同,但是它们也有略微不同的地方. JS手册中对call方法的解释是: call方法:调用一个对象的一个方法,以另一个对象替换当前对象. ...

  2. Java企业微信开发_Exception_02_java.security.InvalidKeyException: Illegal key size

    今天换了重新装了一个jdk,然后运行昨天还好好的企业微信工程,结果启动的时候就给我报了这么个错: java.security.InvalidKeyException: Illegal key size ...

  3. NFS启动时报错Linux NFS:could not open connection for tcp6

    1.1 启动时出现的错误 [root@znix ~]#/etc/init.d/nfs start Shutting down NFS daemon:                          ...

  4. 0_Simple__simpleAtomicIntrinsics + 0_Simple__simpleAtomicIntrinsics_nvrtc

    原子操作.并且在静态代码和运行时编译两种条件下使用. ▶ 源代码:静态使用 #ifndef _SIMPLEATOMICS_KERNEL_H_ #define _SIMPLEATOMICS_KERNEL ...

  5. AngularJS学习篇(十六)

    AngularJS 表单 HTML 控件 以下 HTML input 元素被称为 HTML 控件: input 元素 select 元素 button 元素 textarea 元素 HTML 表单 H ...

  6. js input输入事件兼容性问题

    if(navigator.userAgent.indexOf('Android') > -1){ $("#sign").on("input", funct ...

  7. ubuntu 14.04搭建PHP项目基本流程

    首先准备需要安装东西的列表1.apache服务器,2.php,3.mysql,4.几个软件包的链接包,安装方式是以apt-get方式安装; 1.安装apache服务器: apt-get install ...

  8. Hadoop 2.2.0单节点的伪分布集成环境搭建

    Hadoop版本发展历史 第一代Hadoop被称为Hadoop 1.0 1)0.20.x 2)0.21.x 3)0.22.x 第二代Hadoop被称为Hadoop 2.0(HDFS Federatio ...

  9. C#实现将输入的数自动转换为科学计数法

    一朋友写了一个把输入的整型或浮点数转换为科学计数法表示的算法,写好后叫我去帮他看看有没有什么bug之类的没有考虑周全.我还没有细看就已经把我吓到了----整整写了将近三百行代码.我也没说他什么,只是回 ...

  10. 《天书夜读:从汇编语言到windows内核编程》七 内核字符串与内存

    1)驱动中的字符串使用如下结构: typedef struct _UNICODE_STRING{ USHORT Length; //字符串的长度(字节数) USHORT MaximumLength; ...