テーブルを定義するときは、論理グループの列とグループ自体を目的別に並べると便利です。テーブル内の列の論理的な順序は、開発者に意味を伝え、優れたスタイルの要素です。
それは明らかです。
ただし、明確ではないのは、テーブル内の列の論理的な順序がストレージレイヤーでの物理的な順序に影響するのか、それとも他の重要な影響があるのかです。
スタイルへの影響とは別に、列の順序は重要ですか?
これについては Stack Overflowに関する質問 がありますが、信頼できる回答がありません。
テーブル内の列の論理的な順序は、ストレージレイヤーでの物理的な順序に影響を与えますか? はい
それが重要であるかどうかは、私が(まだ)答えることができない別の問題です。
レコードの構造 に関するPaul Randalの頻繁にリンクされる記事で説明されている方法と同様に、DBCC INDを使用した単純な2列のテーブルを見てみましょう。
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からの出力では、c2の「B」の前に文字「A」が詰められたc1が表示されます。
Memory Dump @0x000000000D25A060
0000000000000000: 10001c00 01000000 41414141 41414141 †........AAAAAAAA
0000000000000010: 41414242 42424242 42424242 030000††††AABBBBBBBBBB...
そして、それだけで、バストを開いてみましょうRowStructure.mdf
16進エディタを使用して、「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...
繰り返しになりますが、データファイルの16進ダンプを確認してみましょう。
レコードの構造 で説明されているように、レコードの固定長と可変長の列は、別個のブロックに格納されます。固定列型と可変列型を論理的にインターリーブしても、物理レコードには影響しません。ただし、各ブロック内では、列の順序はデータファイルのバイトの順序にマップされます。
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ではヒープの列の物理的な順序は保証されていませんが、インデックスでは保証されていると思います。あなたの質問に答えるには、いいえ、定義内の列の順序は重要ではありません。データを読み取るときに重要ではないためです(これはonlyヒープの場合-インデックスは別の問題です)。 。
更新
実際には2つの質問をしています。「テーブル内の列の論理的な順序がストレージレイヤーでの物理的な順序に影響を与えるかどうか」はノーです。メタデータで定義されている論理的な順序は、物理的な順序と同じである必要はありません。答えを探している私が収集するのは、CREATE TABLEの論理的な順序が、作成時に物理的に同じ順序になるかどうかです(これはヒープについてはわかりません)。ただし、上記の警告があります。
SQL Serverでの列の順序を見て読んだ結果に基づくと、違いはありません。ストレージエンジンは、CREATE TABLEステートメントでの指定方法に関係なく、列を行に配置します。そうは言っても、問題となる非常に孤立したEdgeのケースがいくつかあると私は確信していますが、これらについて単一の明確な答えを得るのは難しいでしょう。 Paul Randalの " Inside The Storage Engine "ブログカテゴリの投稿は、私が認識しているストレージエンジンのしくみに関するすべての詳細の最良の情報源です。順序が重要となるEdgeケースを見つけるには、ストレージが機能するさまざまな方法をすべて検討し、すべてのユースケースに対してそれをマトリックス化する必要があると思います。私の状況に当てはまる特定のEdgeケースが指摘されていない限り、CREATE TABLEで列を論理的に順序付けるだけです。これがお役に立てば幸いです。
私はあなたの意味を理解します。設計の観点からは、次のようなテーブルです。
**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN
次のようなテーブルよりもはるかに優れています。
**EMPLOYEES**
LastName
EmployeeID
SSN
Birthday
FirstName
ただし、次のようなtsqlを発行する場合、データベースエンジンは実際の論理列の順序を気にしません。
SELECT FirstName, LastName, SSN FROM Employees
エンジンは、FirstNameのリストがディスクのどこに格納されているかを知っているだけです。