SQL Server :理解数据记录结构

SQL Server :理解数据页结构我们提到每条记录都有7 bytes的系统行开销,那这个7 bytes行开销到底是一个什么样的结构,我们一起来看下。

数据记录存储我们具体的数据,换句话说,它存在堆表里,或者存在聚集索引的叶子节点。数据记录结构是为了让SQL Server更高效的管理数据。我们来看下数据记录结构示意图:

上图中蓝色部分是所有数据记录部分,绿色部分是表结构里取决于定长/变长列的数据记录部分。

行头系统数据:

用做状态位1的第1字节(8位)是用来定义记录的属性:

  • 第0位:版本信息,在SQL Server 2008里始终是0;
  • 第1-3位:这3位用来定义记录类型;
    • 0 数据记录(data record)
    • 1 转发记录(Forwarded record)
    • 2 转发存根(a forwarding stub)
    • 3 索引记录(Index record)
    • 4 二进制堆碎片或行溢出数据(blob fragment or row overflow data)
    • 5 鬼影索引记录(ghost index record)
    • 6 鬼影数据记录(ghost data record)
    • 7 鬼影版本记录(ghost version record)
  • 第4位:存在空值位图(Null bitmap )或没有。在SQL Server 2008里没有不为空的列也会有空值位图(Null bitmap );
  • 第5位:表示是否存在变长列;
  • 第6位:表示该列包含版本信息;
  • 第7位:在SQL Server里未使用;

用作状态位2的第2字节(8位)。只有1位用来表示这条记录是否为鬼影转发记录(ghost forwarded record)。

由行头开始到定长列结尾长度:

下2个字节用来存储行头开始到定长列结尾长度。它包含2个状态位,2个字节用作这个列表示在表中定长数据的实际长度。例如如果表里没有定长列,这个列的值会是4。这和页头列pminlen显示的值是一样的。

所有定长列字段值(Fixed_Data_Size):

下n个字节用来存储在表中的定长数据,n就是在表中所有定长列的长度。如果表里的所有列都是变长列,这一部分就没有。

空值位图(Null_Bitmap):

下2个字节用来存储表里的列数。

下n个字节用作空值位图,每个bit对应一个列,1表示对应列为空。n的值为:列数 / 8,将值取整。

Variable_Data_Size:

下2个字节用来存储表里变长列个数。

下n个字节用来存储每个变长列结束为止的偏移量。每个变长列需要2字节,n的值为:变长列数 * 2 。

最后n个字节用来存储所有变长列值,n的值为所有变长列的实际长度的总长度。

我们来看一个具体的例子:

创建数据库,并插入2条记录

 1 USE [InternalStorageFormat]
 2 GO
 3
 4 IF EXISTS ( SELECT  *
 5             FROM    sysobjects
 6             WHERE   id = OBJECT_ID(N‘[dbo].[Customers]‘)
 7                     AND OBJECTPROPERTY(id, N‘IsUserTable‘) = 1 )
 8     DROP TABLE dbo.Customers
 9
10 CREATE TABLE Customers
11 (
12    FirstName CHAR(50) NOT NULL,
13    LastName CHAR(50) NOT NULL,
14    Address CHAR(100) NOT NULL,
15    ZipCode CHAR(5) NOT NULL,
16    Rating INT NOT NULL,
17    ModifiedDate DATETIME NOT NULL,
18 )
19 GO
20
21
22 INSERT INTO dbo.Customers
23         ( FirstName ,
24           LastName ,
25           Address ,
26           ZipCode ,
27           Rating ,
28           ModifiedDate
29         )
30 VALUES  ( ‘Woody‘ , -- FirstName - char(50)
31           ‘Tu‘ , -- LastName - char(50)
32           ‘ZUOQIAO YOUXI TOWN LINHAI CITY‘ , -- Address - char(50)
33           ‘0000‘ , -- ZipCode - char(5)
34           1 , -- Rating - int
35           ‘2015-05-07 10:09:51‘  -- ModifiedDate - datetime
36         )
37         go 2

使用DBCC IND命令查看表对应页列表:

1 DBCC IND(‘InternalStorageFormat‘,‘Customers‘,-1)

我们看到数据页号为79。

使用DBCC PAGE命令查看页信息:

1 DBCC TRACEON(3604)
2 DBCC PAGE(InternalStorageFormat,1,79,3)
3 GO  

在页头pminlen的值是221,包括定长列的总长217 bytes(50+50+100+5+4+8),2 bytes用作状态位(行头系统开销),2 byte 用作由行头开始到定长列结尾长度。

在记录槽提到的长度224,包括页头pminlen的值,1 byte用作空值位图(6/8 取整为1)和2 bytes 的字段个数。

我们来看一个变长列的表。

创建表并插入数据后,查看表对应的页:

 1 CREATE TABLE VariableLength(
 2    Title         CHAR(10) NOT NULL,
 3    FirstName     VARCHAR(100),
 4    Lastname      VARCHAR(100),
 5    email         VARCHAR(50),
 6    dob           date NOT NULL,
 7    phone         CHAR(10),
 8    Countrycode   CHAR(3),
 9    Designation   VARCHAR(100),
10    PersonalPreference VARCHAR(100)
11 )
12 GO
13 INSERT INTO VariableLength VALUES (‘Mr‘,‘Woody‘,‘Tu‘,‘[email protected]‘,‘2015-5-7‘,‘XXXXXXXXXX‘,‘Chn‘,‘DBA‘,‘Nothing Spl‘)
14 GO
15 DBCC IND(‘InternalStorageFormat‘,‘VariableLength‘,-1)

我们看到数据页号为202。

使用DBCC PAGE命令查看页信息:

1 DBCC TRACEON(3604)
2 GO
3 DBCC PAGE(‘InternalStorageFormat‘,1,202,3)--记得根据你的实际数据库,修改页号202

pminlen值为30,包含:

  • 1 byte 状态位1
  • 1 byte 状态为2
  • 2 bytes 存储行头开始到定长列结尾长度
  • 26 bytes 所有定长列总长度(10+3+10+3:tittle,dob,phone,countrycode)
    • Title  CHAR(10) NOT NULL
    • dob date NOT NULL
    • phone CHAR(10)
    • Countrycode CHAR(3)

可以用下列语句验证下定长列总长度:

1 SELECT DATALENGTH(Title) title,DATALENGTH(dob) dob,DATALENGTH(phone) phone,DATALENGTH(Countrycode) countrycode FROM VariableLength

在槽0显示的81长度包含:

  • 1 byte 状态位1
  • 1 byte 状态为2
  • 2 bytes 存储行头开始到定长列结尾长度
  • 26 bytes 所有定长列总长度(10+3+10+3:tittle,dob,phone,countrycode)
    • Title  CHAR(10) NOT NULL
    • dob date NOT NULL
    • phone CHAR(10)
    • Countrycode CHAR(3)
  • 2 bytes 存储列个数
  • 2 bytes 用作空值位图,字段个数/8后取整,即 9/8 得到2
  • 2 bytes 存储变长列个数
  • 10 bytes 用来存储每个变长列结束位置的偏移量 变长列个数 * 2,即 5 * 2 得到10,5个变长列包含:
    • FirstName VARCHAR(100)
    • Lastname VARCHAR(100)
    • email VARCHAR(50)
    • Designation VARCHAR(100)
    • PersonalPreference VARCHAR(100)
  • 35 bytes 用来存储所有变长列的实际长度,这个可以使用下列语句得到
1 SELECT DATALENGTH(FirstName)+DATALENGTH(Lastname)+DATALENGTH(email)+
2 DATALENGTH(Designation)+DATALENGTH(PersonalPreference) FROM VariableLength

对于在SQL Server里数据记录的存储格式,希望你已经有了清晰的认识。

时间: 2024-12-28 01:15:09

SQL Server :理解数据记录结构的相关文章

SQL Server :理解数据页结构

我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或写入所有数据页.页有不同的类型,像数据页,GAM,SGAM等.在这文章里,让我们一起来理解下数据页结构. SQL Server把数据记录存在数据页(Data Page)里.数据记录是堆表里.聚集索引里叶子节点的行. 数据页由3个部分组成.页头(标头),数据区(数据行和可用空间)及行偏移数组. 在我们讨论在SQL Server里,数据页内部结构具

Sql Server删除数据表中重复记录 三种方法

本文介绍了Sql Server数据库中删除数据表中重复记录的方法. [项目]数据库中users表,包含u_name,u_pwd两个字段,其中u_name存在重复项,现在要实现把重复的项删除![分析]1.生成一张临时表new_users,表结构与users表一样:2.对users表按id做一个循环,每从users表中读出一个条记录,判断new_users中是否存在有相同的u_name,如果没有,则把它插入新表:如果已经有了相同的项,则忽略此条记录:3.把users表改为其它的名称,把new_use

HBase导入SQL Server数据库数据

在先前的几篇随笔中已经介绍了Hadoop.Zookeeper.Hbase的分布式框架搭建方案,目前已经搭建完成了一个包含11个节点的分布式集群.而对于HBase数据库的使用仅限于测试性质的增删改查指令,为了进一步熟悉分布式框架的使用,本文介绍将已有的数据从关系型数据库SQL Server中导入到HBase中的方法. 要完成从关系型数据库到HBase数据的迁移,我们需要使用Sqoop工具,Sqoop是Apache的一个独立项目,设计目的即是在Hadoop(Hive)和传统数据库(MySQL.pos

SQL Server 变更数据捕获(CDC)

原文:SQL Server 变更数据捕获(CDC) 标签:SQL SERVER/MSSQL SERVER/数据库/DBA/字段/对象更改 概述 变更数据捕获用于捕获应用到 SQL Server 表中的插入.更新和删除活动,并以易于使用的关系格式提供这些变更的详细信息.变更数据捕获所使用的更改表中包含镜像所跟踪源表列结构的列,同时还包含了解所发生的变更所需的元数据. 对表开启了变更捕获之后,对该表的所有DML和DDL操作都会被记录,有助于跟踪表的变化. 测试环境: SQL SERVER 2008

SQL Server 批量数据导入

1. 由于Bulk Insert通常配合格式化文件批量导入数据更方便,所以这里先介绍bcp工具导出格式化文件的方法. bcp是SQL Server提供的命令行实用工具提供了数据的导出.导入.格式文件导出等功能,导出格式化文件的语法如下: bcp 数据库名.用户名.表名 format nul -- 这里的nul必须存在,用于不是导出和导入数据的情况下 -f 输出的格式化文件名 [-x] -c -- -x参数指定输出的格式文件为xml格式(默认非xml格式); -c参数指定数据存储方式为字符,并默认

将SQL Server 2000数据导入到MySQL 5.5的方法

一.安装MySQL 5.5(可以与SQL Server不在同一台服务器上),并新建一个空的数据库(一般用utf-8编码),用于接收导入的数据. 二.在SQL Server的服务器上安装mysql-connector-odbc-5.3.2-win32. 三.在SQL Server的服务器上运行"管理工具"->"数据源(ODBC)",切换到"系统DSN"面板,添加"MySQL ODBC 5.3 Unicode Driver"

SQL SERVER之数据查询

 本篇主要讲解查询语句,所有的示例都会按照下面这张表进行. stuID stuName age sex 11090241031 王小虎 21 男 11090241032 王小六 22 男 11090241033 张三 23 男 1.使用where子句查询表中满足条件的记录 比较查询 算术比较查询 算术比较中常用的就是所谓的>.<.<>.=.!<(不小于).!=(不等于)等,比较的语法如下 select* from T_student where age!>30 se

数据库迁移(SQL SERVER导入数据到MySql)

地址:http://blog.csdn.net/jiaohougenyang/article/details/44937801 背景:项目最开始时使用的是SQL Server数据库,业务需求现要将数据库调整为MySQL.网上搜集了一些教程,整理了一个相对简单方便的分享给大家. 1.先去mysql官网下载一个odbc的驱动,因为MSsql一直没有集成mysql的驱动,这个玩意需要单独下载并安装.点我下载  我下载的是windows解压缩的包Windows (x86, 64-bit), ZIP Ar

关于Oracle与SQL Server中数据迁移的办法

最近遇到一个需求,需要把Oracle中一部分表的数据迁移到SQL Server数据库中.但是这些表的结构是有些差异的. 方法一,使用SQL Develper的数据导出工具,导出SQL insert语句,然后再手动修改其中的一些细节,最后在放到SQL Server中执行.因为前后的表结构是有差异的,我需要一条一条语句的去删掉一些字段,然后再删掉一些值,几条或者几十条数据还行,这40万条数据,太多了,这个方法行不通. 方法二,使用C#代码.我用C#写了一个Data Migration的控制台小程序,