我的表格包含3列
| Column Name | Data Type | Size
| Value | real | 4
| LogId | int | 4
| SigId | smallint | 2
为列LogId, SigId
设置了一个主键。
所有大小的总和是4+4+2=10
,但是使用sys.dm_db_index_physical_stats
我得到的是,平均(和最小/最大)记录大小(以字节为单位)是25.有人能解释一下吗?我比较苹果和橘子吗?
答案 0 :(得分:17)
除了实际列值所需的空间之外,物理记录长度还包括行开销。在我的SQL Server实例上,我得到的平均记录长度为17,如下表所示:
CREATE TABLE dbo.Example1(
Value real NOT NULL
, LogId int NOT NULL
, SigId smallint NOT NULL
, CONSTRAINT PK_Example1 PRIMARY KEY CLUSTERED(LogId, SigId)
);
GO
INSERT INTO dbo.Example1 (Value, LogId, SigId) VALUES(1, 2, 3);
GO
SELECT avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID(N'dbo.Example1'),1,0,'DETAILED')
WHERE index_level = 0;
GO
sys.dm_db_index_physical_stats报告的17字节记录长度包括10个字节用于数据,4个字节用于记录头,2个字节用于列计数,1个字节用于NULL位图。有关记录结构的详细信息,请参阅Paul Randal's Anatomy of a record article。
下面是使用DBCC_PAGE转储第一个聚簇索引数据页面的脚本,该脚本由未记录的(不要在生产中使用)sys.dm_db_database_page_allocations
表值函数确定:
DECLARE
@database_id int = DB_ID()
, @object_id int = OBJECT_ID(N'dbo.Example1')
, @allocated_page_file_id int
, @allocated_page_page_id int;
--get first clustered index data page
SELECT
@allocated_page_file_id = allocated_page_file_id
, @allocated_page_page_id = allocated_page_page_id
FROM sys.dm_db_database_page_allocations(@database_id, @object_id, 1, 1, 'DETAILED')
WHERE
page_type_desc = N'DATA_PAGE'
AND previous_page_page_id IS NULL --first page of clustered index;
--dump record
DBCC TRACEON(3604);
DBCC PAGE(@database_id,@allocated_page_file_id,@allocated_page_page_id,1);
DBCC TRACEOFF(3604);
GO
以下是我的实例上的结果的摘录,其中称为物理记录结构字段:
DATA:
Slot 0, Offset 0x60, Length 17, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP Record Size = 17
Memory Dump @0x0000002262C7A060
0000000000000000: 10000e00 02000000 03000000 803f0300 00 .............?...
| | | | | |null bitmap (1 byte)
| | | | |column count (2 bytes)
| | | |Value column data (4-byte real)
| | |SigId column data (2-byte smallint)
| |LogId column data (4-byte int)
|Record header (2-byte record type and 2 byte offset to null bitmap)
至于为什么你的实际记录长度是25而不是17,就像在这个例子中一样,可能的原因是在最初按照Martin在他的评论中建议创建的表之后进行了模式更改。如果数据库启用了行版本化隔离级别,那么Paul的博客文章中会提到额外的开销,但我怀疑这是因为这个开销超过8个字节。