一
通过视图查询表的相关信息
--
关于表相关视图
sys.tables
sys.indexes
sys.columns
sys.check_constraints
sys.default_constraints
sys.key_constraints
sys.allocation_units
sys.partitions
--//TODO
非文档目录视图
sys.system_internals_allocation_units
--
创建测试表
CREATE
TABLE dbo.employee (
emp_lname varchar(15) NOT NULL,
emp_fname varchar(10) NOT NULL,
address varchar(30) NOT NULL,
phone char(12) NOT NULL,
job_level smallint NOT NULL
)
select
* from sys.tables where name = 'employee' and type = 'U'
select
* from sys.columns where object_id = OBJECT_ID('employee')
SELECT
object_id, name, index_id, type_desc
FROM
sys.indexes
WHERE
object_id=object_id('dbo.employee')
SELECT
*
FROM
sys.partitions
WHERE
object_id=object_id('dbo.employee')
--
信息架构视图
SELECT
* FROM DEMO.INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = N'employee'
select
* from sys.indexes where object_id = OBJECT_ID('Sales')
SELECT
object_name(object_id) AS name,
partition_id, partition_number AS pnum, rows,
allocation_unit_id AS au_id, type_desc as page_type_desc,
total_pages AS pages
FROM
sys.partitions p JOIN sys.allocation_units a
ON p.partition_id = a.container_id
WHERE
object_id=object_id('dbo.employee')
ALTER
TABLE dbo.employee ADD resume_short varchar(8000)
ALTER
TABLE dbo.employee ADD resume_long text
SELECT
convert(char(8),object_name(i.object_id)) AS table_name,
i.name AS index_name, i.index_id, i.type_desc as index_type,
partition_id, partition_number AS pnum, rows,
allocation_unit_id AS au_id, a.type_desc as page_type_desc,
total_pages AS pages
FROM
sys.indexes i JOIN sys.partitions p
ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN sys.allocation_units a
ON p.partition_id = a.container_id
WHERE
i.object_id=object_id('dbo.employee')
二
表的内部存储结构
在
SQL Server
中对于表中的每条记录并没有一个内部的全局行编号。
则是使用文件号、页号、以及页面上的插槽号的组合来唯一标识表中的每条记录。
如:
PAGE: (1:73) Slot 0
-- DBCC Page
参数
DBCC Page ({dbid|dbname}, filenum, pagenum [,printopt])
dbid
包含页面的数据库
ID dbname
包含页面的数据库的名称
filenum
包含页面的文件编号
pagenum
文件内的页面
printopt
可选的输出选项;选用其中一个值:
0:
默认值,输出缓冲区的标题和页面标题
1:
输出缓冲区的标题、页面标题
(
分别输出每一行
)
,以及行偏移量表
2:
输出缓冲区的标题、页面标题
(
整体输出页面
)
,以及行偏移量表
3:
输出缓冲区的标题、页面标题
(
分别输出每一行
)
,以及行偏移量表;
每一行后跟分别列出的它的列值
--
创建数据
CREATE
DATABASE DEMO
GO
--
创建测试数据,并插入测试数据
USE
DEMO
GO
create
table t (col1 int primary key,col2 varchar(10))
go
insert
into t select 1,'AAAAA'
insert
into t select 3,'CCCCC'
insert
into t select 2,'BBBBB'
go
--
非文档
DBCC
命令
查看数据库的分区信息
dbcc
extentinfo(DEMO,t)
--
打开跟踪标记
dbcc
traceon(3604)
--
非文档
DBCC
命令
查看页面信息
dbcc
page(DEMO,1,73,1)
输出以下信息:
DBCC
执行完毕。如果
DBCC
输出了错误信息,请与系统管理员联系。
PAGE: (1:73)
BUFFER: --//TODO
:缓冲区信息
--
缓冲区信息显示了给定页面的缓冲信息。在此
buffer
是指一种内存中的结构,用于管理页面,此段的信息仅当该页面处于内存中才有意义。
BUF @0x02E0EF50
bpage = 0x06C08000 bhash = 0x00000000 bpageno = (1:73)
bdbid = 35 breferences = 0 bUse1 = 2491
bstat = 0x1c0010b blog = 0x212121bb bnext = 0x00000000
PAGE HEADER: --//TODO
:页面报头
共
96
个字节
Page @0x06C08000
m_pageId = (1:73) --
这个页面在数据库中所属的文件号和页面编号
m_headerVersion = 1
m_type = 1
m_typeFlagBits = 0x4
m_level = 0 --
页面在索引中的级别(对于叶子页面总是
0
)
m_flagBits = 0x0
m_objId (AllocUnitId.idObj) = 82
m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057594043301888 --
包含所属页面的分配单元的
ID
Metadata: PartitionId = 72057594038321152 --
该页面所属分区的
ID
Metadata: IndexId = 1 --
该页面的
INDEX ID
Metadata: ObjectId = 2073058421 --
该页面所属对象的
ID
m_prevPage = (0:0) -–
上个页面
m_nextPage = (0:0) –-
下个页面
pminlen = 8 --
记录定长部分的总字节数
m_slotCnt = 3 --
页面上已经使用的插槽(记录)数
m_freeCnt = 8030 --
页面上的空闲字节数
m_freeData = 156 --
该页面的第一块空闲空间的字节偏移量
m_reservedCnt = 0 --
所有事物保留的字节数
m_lsn = (27:80:2) –-
用于修改和更新页面的的值
m_xactReserved = 0 --
最新开始的事物保留的字节数
m_xdesId = (0:0)
m_ghostRecCnt = 0
m_tornBits = 0
--
分配状态
Allocation Status
GAM (1:2) = ALLOCATED
SGAM (1:3) = ALLOCATED
PFS (1:1) = 0x60 MIXED_EXT ALLOCATED 0_PCT_FULL
DIFF (1:6) = CHANGED --
用于标识该页面是否更改,用于差异备份
ML (1:7) = NOT MIN_LOGGED
DATA: --//TODO
:行内数据的数据行
最大为
8060
个字节
--//TODO
:从输出的信息可以看到
这张表一行记录所用到的字节数为
20
个字节
Slot 0, Offset 0x60, Length 20, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Memory Dump @0x39F4C060
--//TODO
:第一行数据
insert
into t select 1,'AAAAA'
00000000: 30000800 01000000 0200fc01 00140041 †..............A
00000010: 41414141 † ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?AAAA
Slot 1, Offset 0x88, Length 20, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Memory Dump @0x39F4C088
--//TODO
:第二行数据
insert
into t select 2,'BBBBB'
00000000: 30000800 02000000 0200fc01 00140042 †..............B
00000010: 42424242 † ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?BBBB
Slot 2, Offset 0x74, Length 20, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Memory Dump @0x39F4C074
--//TODO
:第三行数据
insert
into t select 3,'CCCCC'
00000000: 30000800 03000000 0200fc01 00140043 †..............C
00000010: 43434343 † ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?† ?CCCC
OFFSET TABLE: --//TODO
:行偏移矩阵
又称偏移表
Row - Offset
2 (0x2) - 116 (0x74)
1 (0x1) - 136 (0x88)
0 (0x0) - 96 (0x60)
--//TODO
:这个偏移表表示了记录在页面上的逻辑顺序。比如:如果一张表上有聚集索引,
SQL Server
就按照聚集索引来存储记录。这并不意味记录在页面上的物理存储是按照聚集索引键值的顺序来的。
由偏移表给出的信息可以看出
表中的数据的逻辑顺序与物理顺序是不一致的;
如果你删除掉主键或创建聚集索引,则物理顺序与逻辑顺序将一致。
DBCC
执行完毕。如果
DBCC
输出了错误信息,请与系统管理员郭强联系。
---------------------------------------------
-- 1
查看数据库最原始的创建日期
---------------------------------------------
select
create_date from sys.databases where name = 'DEMO'
--2008-06-28 09:19:11.687
DBCC
Page(DEMO,1,9,3)
可以看到以下信息:
dbi_crdate = 2008-06-28 09:19:11.543
--2
查看
delete
是否真正删除数据
delete
from t
select
* from t
dbcc
page(DEMO,1,73,1)
--//TODO
:
可以看到如下信息:
原来的
m_slotCnt = 3
现在为
m_slotCnt = 1
--//TODO
:
只有一条记录
OFFSET TABLE:
Row - Offset
0 (0x0) - 116 (0x74)
--
插入三条记录
insert
into t select 4,'DDDDD'
insert
into t select 5,'EEEEE'
insert
into t select 6,'FFFFF'
go
select
* from t
--
查看数据库的分区信息
dbcc
extentinfo(DEMO,t)
--
打开跟踪标记
dbcc
traceon(3604)
--
查看页面信息
dbcc
page(DEMO,1,73,1)
--//TODO
:
从输出的信息可以看出该页的内容并没有全部删除,而是保存了一行记录,下次插入数据时,并不是从页面的最开始分配空间。
--
删除掉数据
truncate
table t
--
删除表
drop
table t
--//TODO
:
从输出的信息可以看出,
truncate
和
drop
也同样没有立刻删除数据
--3
差异备份是如何实现的
--//TODO
:
差异备份主要寻找
DIFF (1:6) = CHANGED
的页面
如果做完全备份后
这些标记将改为
DIFF (1:6) = NOT CHANGED
三
表物理存储中的数据分析
1
所有列都是定长的字段
drop
table test
CREATE
TABLE test
(
Col1 int NOT NULL,
Col2 char(5) NOT NULL,
Col3 char(5) NOT NULL,
Col4 char(5) NULL,
Col5 int NULL,
Col6 char(5) NOT NULl
)
insert
into test values(1,'AAAAA','BBBBB',NULL,NULL,'CCCCC')
dbcc
extentinfo(demo,test)
dbcc
traceon(3604)
dbcc
page(demo,1,119,1)
SELECT
object_name(object_id) AS name,
rows, type_desc as page_type_desc,
total_pages AS pages, first_page
FROM
sys.partitions p JOIN sys.system_internals_allocation_units a
ON p.partition_id = a.container_id
WHERE
object_id=object_id('dbo.test')
select
dbo.uf_convert_page_nums (0x770000000100)
DBCC
IND(DEMO,test,-1)
SELECT
c.name AS column_name, column_id, max_inrow_length,
pc.system_type_id, leaf_offset
FROM sys.system_internals_partition_columns pc
JOIN sys.partitions p
ON p.partition_id = pc.partition_id
JOIN sys.columns c
ON column_id = partition_column_id
AND c.object_id = p.object_id
WHERE
p.object_id=object_id('test')
PAGE: (1:119)
BUFFER:
BUF @0x02E63450
bpage = 0x08F88000
bhash = 0x00000000 bpageno = (1:119)
bdbid = 35
breferences = 0 bUse1 = 53031
bstat = 0x1c0000b
blog = 0xa2159bbb bnext = 0x00000000
PAGE HEADER:
Page @0x08F88000
m_pageId = (1:119)
m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x4
m_level = 0 m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 98
m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057594044350464
Metadata: PartitionId = 72057594039173120
Metadata: IndexId = 0
Metadata: ObjectId = 197575742
m_prevPage = (0:0) m_nextPage = (0:0)
pminlen = 32
m_slotCnt = 1 m_freeCnt = 8059
m_freeData = 131
m_reservedCnt = 0 m_lsn = (116:1299:19)
m_xactReserved = 0
m_xdesId = (0:0) m_ghostRecCnt = 0
m_tornBits = 0
Allocation Status
GAM (1:2) = ALLOCATED
SGAM (1:3) = ALLOCATED
PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL
DIFF (1:6) = CHANGED
ML (1:7) = NOT MIN_LOGGED
DATA:
Slot 0, Offset 0x60, Length 35, DumpStyle BYTE
Record Type = PRIMARY_RECORD
Record Attributes = NULL_BITMAP
Memory Dump @0x39ECC060
00000000:
10002000 01000000 41414141 41424242 ?.. .....AAAAABBB
00000010:
42420000 00000000 00001b43 43434343 ?BB.........CCCCC
00000020:
0600d8???????????????????????????????...
OFFSET TABLE:
Row - Offset
0 (0x0) - 96 (0x60)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
SELECT
c.name AS column_name, column_id, max_inrow_length,
pc.system_type_id, leaf_offset
FROM sys.system_internals_partition_columns pc
JOIN sys.partitions p
ON p.partition_id = pc.partition_id
JOIN sys.columns c
ON column_id = partition_column_id
AND c.object_id = p.object_id
WHERE
p.object_id=object_id('test')
Col1
1 4 56 4
Col2
2 5 175 8
Col3
3 5 175 13
Col4
4 5 175 18
Col5
5 4 56 23
Col6
6 5 175 27
--
解析字段值
--
定长字段的长度为
32
4 8 13 18 23 27
10 00 2000 01000000 41414141 41424242 42420000 00000000 00001b43 43434343 0600 d8
1 AAAA A BBB B B NULL NULL C C C C C 6 11011000(
从高位到地位
第四,五为“
1
”表示第四,五个字段为
NULL)