表定義中的列順序是否重要?
定義表時,按目的對邏輯組中的列和組本身進行排序會很有幫助。表格中列的邏輯順序向開發人員傳達了意義,並且是良好風格的一個元素。
這很清楚。
然而,不清楚的是,表中列的邏輯順序是否對它們在儲存層的物理順序有任何影響,或者是否有任何其他人可能關心的影響。
除了對樣式的影響之外,列順序是否重要?
Stack Overflow上有一個關於這個的問題,但它缺乏權威的答案。
表中列的邏輯順序對它們在儲存層的物理順序有影響嗎?是的。
是否重要是一個不同的問題,我(還)無法回答。
以與 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
在 DBCC PAGE 的輸出中,我們看到 c1 在 c2 的“B”之前填充了字元“A”:
Memory Dump @0x000000000D25A060 0000000000000000: 10001c00 01000000 41414141 41414141 †........AAAAAAAA 0000000000000010: 41414242 42424242 42424242 030000††††AABBBBBBBBBB...
正因為如此,讓我們
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
這次我們的 DBCC PAGE 輸出不同,首先出現的是“B”字元串:
Memory Dump @0x000000000FC2A060 0000000000000000: 10001c00 01000000 42424242 42424242 †........BBBBBBBB 0000000000000010: 42424141 41414141 41414141 030000††††BBAAAAAAAAAA...
再次,只是為了咯咯笑,讓我們檢查數據文件的十六進制轉儲:
正如Anatomy of a Record解釋的那樣,記錄的固定和可變長度列儲存在不同的塊中。邏輯上交錯的固定和可變列類型與物理記錄無關。但是,在每個塊中,列的順序確實映射到數據文件中的字節順序。
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
也可以看看:
如果你沒有定義聚集索引,你會得到一個堆表。對於堆表,您將始終在讀取數據時進行掃描,因此將讀取整行,從而使列的順序成為一個有爭議的問題。
一旦定義了聚集索引,數據就會在物理上重新排列以符合您指定的列的物理順序——此時,物理順序變得很重要。物理順序是根據您使用的謂詞確定搜尋操作員資格的原因。
雖然我不記得在任何地方讀過它,但我假設 SQL Server 不保證堆的列的物理順序,但它會保證索引。要回答您的問題,不,定義中列的順序應該無關緊要,因為它們在讀取數據時無關緊要(請注意,這僅適用於堆 - 索引是另一回事)。
更新
實際上,您要問兩個問題-“表中列的邏輯順序是否對它們在儲存層的物理順序有任何影響”是否定的。元數據定義的邏輯順序不必與物理順序相同。我收集到您正在尋找的答案是 CREATE TABLE 中的邏輯順序是否導致創建時的物理順序相同 - 我不知道,對於堆 - 儘管有上面的警告。