テーブルを定義するとき、論理グループ内の列とグループ自体を目的別に並べると便利です。テーブル内の列の論理的な順序は、開発者に意味を伝え、良いスタイルの要素です。
それは明らかです。
ただし、テーブル内の列の論理的な順序がストレージレイヤーでの物理的な順序に影響を与えるかどうか、または気になるその他の影響があるかどうかは明らかではありません。
スタイルへの影響とは別に、列の順序は重要ですか?
これについてStack Overflowに質問がありますが、信頼できる答えがありません。
テーブルを定義するとき、論理グループ内の列とグループ自体を目的別に並べると便利です。テーブル内の列の論理的な順序は、開発者に意味を伝え、良いスタイルの要素です。
それは明らかです。
ただし、テーブル内の列の論理的な順序がストレージレイヤーでの物理的な順序に影響を与えるかどうか、または気になるその他の影響があるかどうかは明らかではありません。
スタイルへの影響とは別に、列の順序は重要ですか?
これについて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
こちらもご覧ください:
C
収まりきらず、独自の拡張ページに入ります。そのためselect A, B
、YourTableからはのページ読み取りの半分しか必要ありませんselect A, C from YourTable
。
"Whether it matters or not is a different issue that I can't answer (yet)."
:列の順序はパフォーマンスに大きく影響する可能性があります。さらに、エラーに影響する可能性もあります。このチェックそれが良いと思いデモ2ショー-
クラスター化インデックスを定義しない場合、ヒープテーブルが取得されます。ヒープテーブルの場合、データの読み取り時には常にスキャンが行われるため、行全体が読み取られ、列の順序が重要なポイントになります。
クラスター化インデックスを定義するとすぐに、指定した列の物理的な順序に合わせてデータが物理的に再配置されます。この時点で、物理的な順序が重要になります。物理的な順序は、使用している述語に基づいて検索演算子の適格性を決定するものです。
どこでも読んだことを思い出せませんが、SQL Serverはヒープの列の物理的な順序を保証しないと思いますが、インデックスの場合は保証されます。あなたの質問に答えるには、いいえ、定義の列の順序は、データを読み込むときに関係ないので重要ではありません(これはヒープ専用であることに注意してください-インデックスは別の問題です)。
更新
実際には、「テーブル内の列の論理的な順序がストレージレイヤーでの物理的な順序に影響を与えるかどうか」という2つの質問をしています。メタデータによって定義される論理的な順序は、物理的な順序と同じ順序である必要はありません。答えを探しているのは、CREATE TABLEの論理的な順序が、作成時に同じ物理的な順序になるかどうかです(ヒープについてはわかりませんが)。
私が見たものと読んだものに基づいて、SQL Serverの列の順序に違いはありません。ストレージエンジンは、CREATE TABLEステートメントでの列の指定に関係なく、列を行に配置します。そうは言っても、それが問題になる非常に孤立したエッジケースがいくつかあると確信していますが、これらについての単一の明確な答えを得るのに苦労すると思います。ポールランダルの「ストレージエンジンの内部」ブログカテゴリの投稿は、ストレージエンジンがどのように機能するかについてのすべての詳細の最良の情報源です。私の状況に当てはまる特定のエッジケースが指摘されていない限り、CREATE TABLEで列を論理的に並べるだけです。
意味がわかります。設計の観点から、次のような表:
**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN
次のような表よりもはるかに優れています。
**EMPLOYEES**
LastName
EmployeeID
SSN
Birthday
FirstName
ただし、次のようなtsqlを発行した場合、データベースエンジンは論理列の順序を実際に気にしません。
SELECT FirstName, LastName, SSN FROM Employees
エンジンは、FirstNameのリストがディスクのどこに保存されているかを知っています。
CREATE TABLE
ステートメントに従っていることを発見しました(CIキー列がセクションの最初に来ることを除いて)。ただし、ALTER COLUMN
データ型/列の長さを変更すると、列の順序が変わる可能性があります。私が考えることができることを重要わずかな場合は、空の文字列またはNULLと可変長部分の末尾の列が(2008内部帳にカレン・ディレイニーによって証明)列オフセット配列内のすべてのではスペースを取らないということです