Sql server SQL Server:记录大小大于预期值

Sql server SQL Server:记录大小大于预期值,sql-server,Sql Server,我的表由3列组成 | Column Name | Data Type | Size | Value | real | 4 | LogId | int | 4 | SigId | smallint | 2 为列LogId、SigId设置一个主键 所有大小的总和是4+4+2=10,但是使用sys.dm\u db\u index\u physical\u stats我得到,以字节为单位的平均(和最小/最大)记录大小是25。有人能解释一下吗?

我的表由3列组成

| Column Name | Data Type | Size
| Value       | real      | 4
| LogId       | int       | 4
| SigId       | smallint  | 2
为列
LogId、SigId
设置一个主键


所有大小的总和是
4+4+2=10
,但是使用
sys.dm\u db\u index\u physical\u stats
我得到,以字节为单位的平均(和最小/最大)记录大小是25。有人能解释一下吗?我在比较苹果和橙子吗?

除了实际列值所需的空间之外,物理记录长度还包括行开销。在我的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个字节的空位图。有关记录结构的详细信息,请参阅

下面是一个脚本,用于使用未记录的(不要在生产中使用)sys.dm\u db\u database\u page\u分配所确定的DBCC\u page转储第一个聚集索引数据页表值函数:

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个字节。

数据库的允许快照隔离设置是什么?可能相关,我曾经在磁盘上有一个约15MB的文本文件目录,尽管它们的实际大小约为500KB,可能是因为“分配单元大小”。可能记录/列/表/等越多,数字越能反映问题。@edwinstoeler快照隔离状态为0您能否显示
sys.dm\u db\u index\u physical\u stats
的输出副本?我预计这将占用17个字节(如下所示)。也许你有8个字节被删除或更改的列占用了。首先看新年快乐。我终于回到办公室,能够测试这个。事实上,我完全重建了表,得到的平均行大小为17!非常感谢。