Nic*_*mas 38 sql-server-2008 database-design sql-server database-internals
定义表时,按目的对逻辑组中的列和组本身进行排序会很有帮助。表中列的逻辑顺序向开发人员传达了意义,是良好风格的元素。
这是清楚的。
然而,不清楚的是,表中列的逻辑顺序是否对其在存储层的物理顺序有任何影响,或者是否有任何其他人可能关心的影响。
除了对样式的影响之外,列顺序是否重要?
Stack Overflow 上有一个关于这个的问题,但它缺乏权威的答案。
Mar*_*ith 24
表中列的逻辑顺序对它们在存储层的物理顺序有任何影响吗?是的。
它是否重要是一个不同的问题,我无法回答(还)。
与 Paul Randal 的关于记录剖析的频繁链接文章中描述的方式类似,让我们看一下带有 DBCC IND 的简单的两列表:
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
USE master;
GO
IF DATABASEPROPERTY (N'RowStructure', 'Version') > 0 DROP DATABASE RowStructure;
GO
CREATE DATABASE RowStructure;
GO
USE RowStructure;
GO
CREATE TABLE FixedLengthOrder
(
c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, c2 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL
, c3 CHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL
);
GO
INSERT FixedLengthOrder DEFAULT VALUES;
GO
DBCC IND ('RowStructure', 'FixedLengthOrder', 1);
GO
Run Code Online (Sandbox Code Playgroud)

上面的输出表明我们需要查看第 89 页:
DBCC TRACEON (3604);
GO
DBCC PAGE ('RowStructure', 1, 89, 3);
GO
Run Code Online (Sandbox Code Playgroud)
在 DBCC PAGE 的输出中,我们看到 c1 在 c2 的 'B' 之前塞满了字符 'A':
Memory Dump @0x000000000D25A060
0000000000000000: 10001c00 01000000 41414141 41414141 †........AAAAAAAA
0000000000000010: 41414242 42424242 42424242 030000††††AABBBBBBBBBB...
Run Code Online (Sandbox Code Playgroud)
仅仅因为,让我们RowStructure.mdf用十六进制编辑器打开并确认 'A' 字符串在 'B' 字符串之前:

现在重复测试但颠倒字符串的顺序,将 'B' 字符放在 c1 中,将 'A' 字符放在 c2 中:
CREATE TABLE FixedLengthOrder
(
c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, c2 CHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL
, c3 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL
);
GO
Run Code Online (Sandbox Code Playgroud)
这次我们的 DBCC PAGE 输出不同,'B' 字符串首先出现:
Memory Dump @0x000000000FC2A060
0000000000000000: 10001c00 01000000 42424242 42424242 †........BBBBBBBB
0000000000000010: 42424141 41414141 41414141 030000††††BBAAAAAAAAAA...
Run Code Online (Sandbox Code Playgroud)
再次,为了咯咯的笑声,让我们检查数据文件的十六进制转储:
正如记录剖析所解释的那样,记录的固定长度和可变长度列存储在不同的块中。逻辑上交错的固定和可变列类型与物理记录无关。但是,在每个块中,列的顺序确实映射到数据文件中的字节顺序。
CREATE TABLE FixedAndVariableColumns
(
c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, c2 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL
, c3 VARCHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL
, c4 CHAR(10) DEFAULT REPLICATE('C', 10) NOT NULL
, c5 VARCHAR(10) DEFAULT REPLICATE('D', 10) NOT NULL
, c6 CHAR(10) DEFAULT REPLICATE('E', 10) NOT NULL
);
GO
Memory Dump @0x000000000E07C060
0000000000000000: 30002600 01000000 41414141 41414141 †0.&.....AAAAAAAA
0000000000000010: 41414343 43434343 43434343 45454545 †AACCCCCCCCCCEEEE
0000000000000020: 45454545 45450600 00020039 00430042 †EEEEEE.....9.C.B
0000000000000030: 42424242 42424242 42444444 44444444 †BBBBBBBBBDDDDDDD
0000000000000040: 444444†††††††††††††††††††††††††††††††DDD
Run Code Online (Sandbox Code Playgroud)
也可以看看:
如果你没有定义聚集索引,你会得到一个堆表。对于堆表,您在读取数据时将始终进行扫描,因此将读取整行,从而使列的顺序成为一个有争议的问题。
一旦您定义了聚集索引,数据就会在物理上重新排列以符合您指定的列的物理顺序——此时,物理顺序变得很重要。物理顺序是根据您使用的谓词确定寻找运算符资格的因素。
虽然我不记得在任何地方读过它,但我认为 SQL Server 不保证堆的列的物理顺序,而它会保证索引。要回答您的问题,不,定义中列的顺序应该无关紧要,因为它们在读取数据时无关紧要(请注意,这仅适用于堆 - 索引是另一回事)。
更新
实际上你在问两个问题——“表中列的逻辑顺序是否对它们在存储层的物理顺序有任何影响”是否定的。元数据定义的逻辑顺序不必与物理顺序相同。我认为您正在寻找的答案是 CREATE TABLE 中的逻辑顺序是否在创建时产生相同的物理顺序 - 我不知道,对于堆 - 尽管有上面的警告。
| 归档时间: |
|
| 查看次数: |
18071 次 |
| 最近记录: |