定义表时,按目的对逻辑组中的列和组本身进行排序会很有帮助。表中列的逻辑顺序将含义传达给开发人员,并且是一个良好的样式元素。

这很清楚。表中列的逻辑顺序对其在存储层的物理顺序有任何影响,或者是否有其他可能影响的影响。

除了对样式的影响之外,列是否

在Stack Overflow上有一个关于此的问题,但它缺乏权威性的答案。

#1 楼

表中列的逻辑顺序对存储层的物理顺序有影响吗?是。

是否重要还是另一个我无法回答的问题。

与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



我们需要看一下第89页: >
DBCC TRACEON (3604);
GO
DBCC PAGE ('RowStructure', 1, 89, 3);
GO


正因为如此,让我们用十六进制编辑器打开RowStructure.mdf并确认'A'字符串位于'B'字符串之前: br />
现在重复测试,但要颠倒字符串的顺序,将'B'字符放入c1并将'A'字符放入c2:

Memory Dump @0x000000000D25A060

0000000000000000:   10001c00 01000000 41414141 41414141 †........AAAAAAAA
0000000000000010:   41414242 42424242 42424242 030000††††AABBBBBBBBBB...


这一次我们的DBCC PAGE输出是不同的,并且'B'字符串首先出现:

数据文件的格式:



正如“记录剖析”所述,记录的固定长度和可变长度列存储在不同的块中。逻辑上交错的固定列和可变列类型与物理记录无关。但是,在每个块中,列的顺序确实映射到数据文件中字节的顺序。

列顺序无关紧要…通常,但是–取决于!!

评论


我同意+1。我一直发现,在每个部分中,列的顺序最初都是按照CREATE TABLE语句进行的(除了CI键列确实排在该部分的首位)。尽管如果ALTER COLUMN更改数据类型/列长度,则列的顺序可以更改。我能想到的唯一较小的情况是,变量长度部分结尾处带有空字符串或NULL的列在列偏移数组中根本不占空间(由Kalen Delaney在2008年内部手册中演示)

–马丁·史密斯
2012年6月2日在8:33



在极少数情况下,列顺序可能很重要。例如,如果您有一个包含3列A,B和C的表,每个列长3kb。 SQL Server页为8kb,因此C不适合使用,并进入其自己的扩展页。因此,从YourTable中选择A,B仅需要从YourTable中选择A,C读取页面的一半。

–安道尔
15年12月24日在13:44

“是否重要是另一个我无法回答的问题。” :列的顺序会显着影响性能。此外,甚至会影响错误!检查一下-演示2展示得更好

–罗恩·阿里(Ronen Ariely)
19 Mar 23 '19 at 4:40

@RonenAriely有趣的例子,但是在原始问题的背景下有些人为的。您正在演示随后删除列时列顺序如何产生影响。我认为我从来没有设计过具有预见性的表格。

– Mark Storey-Smith
19年4月4日在14:18

嗨@ MarkStorey-Smith。 (1)作为一名建筑师,我总是向您解释,良好的设计与卓越的设计之间的区别在于,良好的设计满足了当前的需求,而卓越的设计满足了未来的需求(尚不为人所知)。 (2)问题的答案为是。答案的实施取决于OP和我们每个人。这不在讨论范围之内,但是我们可以打开此主题进行讨论。但是在stackoverflow论坛系列中却不是,因为该界面不允许进行真正的讨论,而只能在响应中添加一行较差的简短文本

–罗恩·阿里(Ronen Ariely)
19年4月4日在14:52

#2 楼

如果不定义聚簇索引,则会得到一个堆表。对于堆表,在读取数据时将始终进行扫描,因此将读取整行,从而使列的顺序成为问题。

一旦定义了聚集索引,数据在物理上进行了重新排列以符合您指定的列的物理顺序-此时,物理顺序变得很重要。物理顺序是根据您使用的谓词确定寻求操作员资格的因素。列用于堆,而索引将被保证。要回答您的问题,不,定义中的列顺序无关紧要,因为它们在读取数据时无关紧要(请注意,这仅适用于堆-索引是另一回事)。

更新
实际上您是在问两个问题-“表中列的逻辑顺序是否会影响它们在存储层的物理顺序”是“否”。由元数据定义的逻辑顺序不必与物理顺序相同。我要收集的您正在寻找答案的是,尽管上面有警告,但CREATE TABLE中的逻辑顺序是否会导致创建时的物理顺序相同(对于堆,我不知道)。

#3 楼

基于我所看到和阅读的内容,SQL Server中的列顺序没有区别。无论在CREATE TABLE语句中如何指定列,存储引擎都会在行上放置列。话虽这么说,我敢肯定有一些非常孤立的边缘情况确实很重要,但是我认为您很难在这些问题上获得一个明确的答案。 Paul Randal的“ Inside The Storage Engine”博客类别的帖子是我所知道的有关存储引擎如何工作的所有详细信息的最佳来源。我认为您将必须研究存储工作的所有方式以及针对所有用例的矩阵,以找到顺序重要的边缘情况。除非指出适用于我的情况的特殊情况,否则我只是在逻辑上对我的CREATE TABLE进行排序。希望对您有所帮助。

#4 楼

我明白你的意思。从设计角度看,这样的表:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 


比这样的表好很多: />
,但是如果您发出这样的tsql,则数据库引擎并不真正在乎逻辑列的顺序: FirstName的列表存储在磁盘中。