原帖首发于it168专稿,链接为http://tech.it168.com/a2010/0902/1098/000001098556_1.shtmlITPUB个人空间i{(Rht ^1X
之所以写SQL Server 2008存储结构,很大程度上是因为看了《SQL Server 2005技术内幕存储引擎》和《SQL Server 2008 Internals》,其次主要是为了满足自己的好奇心和虚荣心。

  说实话,了解SQLServer2008的存储结构,也许并不会提高你的SQL技能,也许也不会提升你对SQL Server性能优化的能力。出于好玩的目的,希望能够和大家分享一下。

  本文算是对两本书的阅读笔记,加上自己的动手实践和领悟;如果涉及版权问题和原创问题概不负责。

  从直观的角度出发,我们可以观察到SQL Server的物理存储由若干数据库构成,其中

数据库类别

数据库名称

数据库描述

系统数据库

master

master 数据库记录 SQL Server 系统的所有系统级信息。主要包括实例范围的元数据、端点、链接服务器和系统配置设置以及记录了所有其他数据库的存在、数据库文件的位置以及 SQL Server 的初始化信息。

model

提供了SQL Server 实例上创建的所有数据库的模板。

msdb

主要由 SQL Server 代理用于计划警报和作业

tempdb

tempdb 系统数据库是一个全局资源,可供连接到 SQL Server 实例的所有用户使用,并可用于保存显式创建的临时用户对象、SQL Server 数据库引擎创建的内部对象,行版本数据等

户数据库

db1/db2

 

ITPUB个人空间 A+fZ5x4TB)O
   如果我们在数据库处点击右键,选择属性,可以在文件处看到:

  每一个数据库无论系统数据库还是用户数据库都是由两类数据库文件构成,即行数据数据库文件和日志文件;而行数据数据库文件则有一个主要数据文件和N个次要数据文件构成。

  我们还可以再考察一下文件组页,每个数据库都有一个Primary主文件组和N个用户定义文件组构成。通过对表对象应用filegroup选项,能够将不同的表分散到不同的磁盘上,以提高系统性能。

  数据库又主要由表、视图、函数、存储过程、触发器、类型、规则、默认值等等构成。

  当然我们主要考察的对象是表,每一个数据库实际上都包含一系列系统表和一系列用户表。

  而表又包括一系列的列、主外键、约束、触发器、索引等。

   SQLServer2008中提供了相当丰富的系统视图,能够从宏观到微观,从静态到动态反应数据库对象的存储结果、系统性能、系统等待事件等等。同时 也保留了与早期版本兼容性的视图,主要差别在于SQLServer2008提供的新系统视图一是更加全面和丰富、二是更注重命名规则。

        SQLServer2008的几乎所有对象信息都存在于sys.objects系统视图中,同时又在不同的系统视图中保留了相应的副本,对于函数、视图、 存储过程、触发器等相应的文本对象,把相应的对象的详细资料存于新的sys.sql_modules视图中。

序号

对象类型

对象类型描述

相关系统表

1

AF = 聚合函数 (CLR)

AGGREGATE_FUNCTION

N/A

2

C = CHECK 约束

CHECK_CONSTRAINT

CHECK_CONSTRAINTS

3

D = DEFAULT(约束或独立)

DEFAULT_CONSTRAINT

DEFAULT_CONSTRAINTS

4

F = FOREIGN KEY 约束

FOREIGN_KEY_CONSTRAINT

FOREIGN_KEYS

5

FN = SQL 标量函数

SQL_SCALAR_FUNCTION

SQL_MODULES

6

FS = 程序集 (CLR) 标量函数

CLR_SCALAR_FUNCTION

N/A

7

FT = 程序集 (CLR) 表值函数

CLR_TABLE_VALUED_FUNCTION

N/A

8

IF = SQL 内联表值函数

SQL_INLINE_TABLE_VALUED_FUNCTION

SQL_MODULES

9

IT = 内部表

INTERNAL_TABLE

INTERNAL_TABLES

10

P = SQL 存储过程

SQL_STORED_PROCEDURE

PROCEDURES

:Bw3D7r]h `6W(YI6517SQL_MODULES

&suSA%G|aeU6517 

11

PC = 程序集 (CLR) 存储过程

CLR_STORED_PROCEDURE

N/A

12

PG = 计划指南

PLAN_GUIDE

PLAN_GUIDES

13

PK = PRIMARY KEY 约束

PRIMARY_KEY_CONSTRAINT

KEY_CONSTRAINTS

14

R = 规则(旧式,独立)

RULE

SQL_MODULES

15

RF = 复制筛选过程

REPLICATION_FILTER_PROCEDURE

SQL_MODULES

16

S = 系统基表

SYSTEM_TABLE

OBJECTS

17

SN = 同义词

SYNONYM

SYNONYMS

18

SQ = 服务队列

SERVICE_QUEUE

SERVICE_QUEUESS

19

TA = 程序集 (CLR) DML 触发器

CLR_TRIGGER

N/A

20

TF = SQL 表值函数

SQL_TABLE_VALUED_FUNCTION

SQL_MODULES

21

TR = SQL DML 触发器

SQL_TRIGGER

TRIGGERSITPUB个人空间? F%v;C5U(e.J

SQL_MODULES

f7A+ZZDY6517 

22

U = 表(用户定义类型)

USER_TABLE

TABLES

23

UQ = UNIQUE 约束

UNIQUE_CONSTRAINT

KEY_CONSTRAINTS

24

V = 视图

VIEW

VIEWS

5}A'o8x@ZSmsh6517SQL_MODULES

4P6q zk&VO6}6517 

25

X = 扩展存储过程

EXTENDED_STORED_PROCEDURE

EXTENDED_PROCEDURES

 对于数据库层面的存储结构,我们可以参看以下视图:



#div_code img { border: 0px none; } 
  
--数据库实例的概要情况
r|hY*huP`6517SELECT*FROM SYS.SERVERS
*C(X9`-@KL d6517WHERE SERVER_ID=0ITPUB个人空间C]ydj)XN0g
--兼容性视图SELECT*FROM SYS.SYSSERVERS
Wd'N6cy2c'd6517
:L+IV5U.z.Q|6517--各个数据库的详细信息ITPUB个人空间/ui0^!e7dj @
SELECT*FROM SYS.DATABASESITPUB个人空间'u8XG~3I1C~r
--兼容性视图SELECT*FROM SYS.SYSDATABASESITPUB个人空间D&cn4z4Iv.U
ITPUB个人空间[4p A+j _g
--文件组的详细信息
(Vc'f9U$H_XQ;Z6517SELECT*FROM SYS.FILEGROUPS  ITPUB个人空间dox\*^b']
--兼容性视图SELECT*FROM SYS.SYSFILEGROUPS
^]7POz4u6517
\wDrS{_ \~gJ6517--各个数据库文件的详细信息ITPUB个人空间9UH'DO6]&Z5^C(mh-n%p
SELECT*FROM SYS.MASTER_FILESITPUB个人空间9y0o"Z:e*@C}
--兼容性视图SELECT*FROM SYS.SYSALTFILESITPUB个人空间3nos#R$WgS FS

.C1Jd*y6mhzk6517--当前数据库文件的详细信息
j;QaZP D/j:Q6517SELECT*FROM SYS.DATABASE_FILES
4j.^$q$CJ5ck/u3biI6517--兼容性视图SELECT*FROM SYS.SYSFILES
8^:`g YU&hz6517ITPUB个人空间ow8Tt|&{$R
--数据空间的详细情况,可以是文件组或分区方案
4tiUU^)e6517SELECT*FROM SYS.DATA_SPACESITPUB个人空间\d{h!so



 

  关于数据库表的存储信息,通过以下系统表我们可以大致了解数据库表在数据库中是如何定义的。以下视图提供了基本的数据库对象信息。



#div_code img { border: 0px none; } 
  
--我们首先创建一张表和一些索引
lS.TJUoIA4_3c6517CREATE TABLE dbo.test
*oNYEg!K$I'U6517(ITPUB个人空间"[[)I%fY|9K&R
   idintIDENTITY(1,1)NOTNULL,
5N Q}.er/D6517  name char(100)NULL,
n3~4GfYO+K6517CONSTRAINT PK_test PRIMARY KEY CLUSTERED (idASC)ITPUB个人空间!U+R%J(Z$VKnm oal
 )ITPUB个人空间N:_r0H~YZ{J&\
 CREATE NONCLUSTERED INDEX IX_testONdbo.test(name)ITPUB个人空间AkV_d9o

8C,{ OS k6517--表和对象详细信息,根据表名称查询出object_id为ITPUB个人空间]%R"nsOa"_"T @*j
--事实上几乎所有的用户对象都出自于SYS.OBJECTS表ITPUB个人空间\,B[5H$i6|L @q
SELECT*FROM SYS.OBJECTSITPUB个人空间{1]R*Us.W
 WHERE type_desc='USER_TABLE' AND NAME='TEST'ITPUB个人空间FM:n? @v
--兼容性视图SYSOBJECTS
6Q}6t)_a/Wr4|F'k6517--如果要查询与该表相关的其他所有对象,则可以执行以下语句ITPUB个人空间e+GWA(t
SELECT*FROM SYS.OBJECTS
ID S D'z&cNc6517WHERE type_desc='USER_TABLE' AND NAME='TEST' OR
[[z*W1gb3Bm6AtT6517       parent_object_id inITPUB个人空间d`'Z]{T i9[;tU
         (SELECTobject_id FROM SYS.OBJECTSITPUB个人空间SJ$LP-Z/p#Xu]
           WHERE type_desc='USER_TABLE' AND NAME='TEST')ITPUB个人空间 f$y:D8j8U p#gx/e
          
/Z+dBt4gp!l6_w6517--表字段详细信息,可以查询出相关column_idITPUB个人空间9EKUDVs^a
SELECT*FROM SYS.COLUMNSITPUB个人空间~"O Z fz#k~
 WHERE OBJECT_ID=5575058ITPUB个人空间:c5[Lv)sE{#QtW
--兼容性视图SYSCOLUMNS
)h(fk;`(|@\6517ITPUB个人空间 J4G2N{q9Ps3L
--表索引详细情况,可以清楚的看到存在两个索引
:p?|h r6517SELECT*FROM SYS.INDEXES WHERE OBJECT_ID=5575058
5QSG1ru+^ y-m0b6517--兼容性视图SYSINDEXES
U] zZ#g0y6517
?du^(n+j6517--表分区情况,数据库中所有表和索引的每个分区在表中各对应一行
U C8Ak F+]6517--此处可以看到该表有两个分区,聚集索引即表本身,还有一个是name的非聚集索引ITPUB个人空间9y8Gc"{?&DB9~
--partition_id 即分区的ID
:Z skZ;\wN{6517--hobt_id包含此分区的行的数据堆或B树的ID  ITPUB个人空间\N,PS4Ycw3M
SELECT*FROM SYS.PARTITIONS WHERE OBJECT_ID=5575058
:^hF A$^6517
Qh,H?3xD^6517--分配单元情况,数据库中的每个分配单元都在表中占一行ITPUB个人空间.k T^;Z4v&^%Vr'nth\
--该表只有和SYS.PARTITIONS配合使用才有意义ITPUB个人空间[)?]^7CZPd W7F
SELECT*FROM SYS.ALLOCATION_UNITS
5J_.@JQ3}lZ!K6517
C WTYLW6517--SYS.ALLOCATION_UNITS和SYS.PARTITIONS一起使用能够反映出某个对象的页面分配和使用情况ITPUB个人空间.Nu/d!N.y7xuQH
SELECT*FROM SYS.ALLOCATION_UNITS U,SYS.PARTITIONS P
KiJ5Jy6517WHERE U.TYPE IN (1,3)ANDU.CONTAINER_ID=P.HOBT_IDANDP.OBJECT_ID=5575058
.@%} D+Lz&?KE+j,j4~6517UNION ALLITPUB个人空间O[#} t,c0h
SELECT*FROM SYS.ALLOCATION_UNITS U,SYS.PARTITIONS P
({.s#} nQ_Id/{S6517WHERE U.TYPE=2ANDU.CONTAINER_ID=P.PARTITION_IDANDP.OBJECT_ID=5575058ITPUB个人空间D)Bg*Fr5a
ITPUB个人空间@qrhym#rzo
--返回每个分区的页和行计数信息ITPUB个人空间vd1C8H$kKCl/I
SELECT*FROM SYS.DM_DB_PARTITION_STATS WHERE OBJECT_ID=5575058
i-^'[?re6}!rM*K&u6517ITPUB个人空间xH`(h9ZJ:O)kcU
--返回索引的详细字段情况ITPUB个人空间 @`!\Ct9m?
SELECT*FROM SYS.INDEX_COLUMNS WHERE OBJECT_ID=5575058ITPUB个人空间4?-o[E~qFN4H#S
--兼容性视图SYSINDEXKEYS
iXQ9h9Yv6ThA6517
j|9Oq.Y6517--以下为根据某个索引名称获取其相关字段的语句
|LMiD#V,E+? ~6517DECLARE @index_field_names VARCHAR(500)
 Nr$`-~ M[X6517SET@index_field_names='';
 x(E A/hM`O;prV-?*c6517SELECT@index_field_names=@index_field_names+c.name+','
"rD _}2j|6517  FROM SYS.INDEX_COLUMNS a,SYS.INDEXES b,SYS.COLUMNS c
 |0y7N;h SY6517WHERE a.object_id=b.object_idANDa.index_id=b.index_id
%y'z4~`~xA6517  ANDa.object_id=c.object_idANDa.column_id=c.column_id
"yqzD8a*S6517  ANDb.name='IX_test2'
$_!m+l9zn6517ORDER BY a.index_column_id
| z:EPEq}6517SET@index_field_names=LEFT(@index_field_names,LEN(@index_field_names)-1)
qN1t9g1z6517PRINT @index_field_names
0VL:`Xl7j L+@?H6517ITPUB个人空间(Rs?q6] u+B
--CHECK约束,数据来源sys.objects.type='C'
M)SR1S c~i}_ A6517SELECT*FROM SYS.CHECK_CONSTRAINTS WHERE OBJECT_ID=?
jhKwG1S!t5L6517--兼容性视图SYSCONSTRAINTSITPUB个人空间F*J8P h+?J8I

*W@/?8c"z1hrw6517--数据来源sys.objects.type=DITPUB个人空间9Y%l:D$w~f
SELECT*FROM SYS.DEFAULT_CONSTRAINTS WHERE OBJECT_ID=?
:`WZa;x W6517--兼容性视图SYSCONSTRAINTSITPUB个人空间pEi(`wM3^
ITPUB个人空间Y_/C2c1E Nr
--主键或唯一约束,数据来源sys.objects.type PK 和UQITPUB个人空间?;f:K&|$m.h!]%n
SELECT*FROM SYS.KEY_CONSTRAINTS WHERE OBJECT_ID=?ITPUB个人空间I_)E.FmrG)q;t#V-yF o
--兼容性视图SYSCONSTRAINTSITPUB个人空间ap|Zxx L
ITPUB个人空间Jl%\$@^$i
--外键,数据来源sys.object.type=FITPUB个人空间`*CBB-N;G
SELECT*FROM SYS.FOREIGN_KEYS WHERE OBJECT_ID=?  ITPUB个人空间b"D:{v,ju
--兼容性视图SYSREFERENCES
;itr.lQ'X~^6517ITPUB个人空间5E|-A+j4h
--触发器ITPUB个人空间:\|:d0mkxL]| Z
SELECT*FROM SYS.TRIGGERS WHERE OBJECT_ID=?  
vk5t9| t8K5R^!f6517ITPUB个人空间iK7ISM7~ VYr
--注释
&Lh"e$O2e;i6`*c6517SELECT*FROM SYS.SQL_MODULES
wpD2Zd-z6517--兼容性视图SYSCOMMENTS
E4bj`+Kp:x/`6517
V4]6O3V&JA E)n C H6517--数据库用户表
w/d'RA+QG&w-f6517SELECT*FROM SYS.DATABASE_PRINCIPALS
:G Xo z5U|8z6517--兼容性视图SYSUSERS
5_.{"EB,m L6517
Jz [.P:M8Is&i[6517--数据库数据类型表ITPUB个人空间,y:J_4x#b
SELECT*FROM SYS.TYPES
"_lB)iR2[^1C6517--兼容性视图SYSTYPES