テーブルの定義内の列の順序は重要ですか?


35

テーブルを定義するとき、論理グループ内の列とグループ自体を目的別に並べると便利です。テーブル内の列の論理的な順序は、開発者に意味を伝え、良いスタイルの要素です。

それは明らかです。

ただし、テーブル内の列の論理的な順序がストレージレイヤーでの物理的な順序に影響を与えるかどうか、または気になるその他の影響があるかどうかは明らかではありません。

スタイルへの影響とは別に、列の順序は重要ですか?

これについてStack Overflowに質問がありますが、信頼できる答えがありません。

回答:


23

テーブル内の列の論理的な順序は、ストレージレイヤーでの物理的な順序に影響を与えますか?はい。

それが重要かどうかは、(まだ)答えられない別の問題です。

レコード構造に関する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

DBCC IND出力

上記の出力は、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」文字列に先行することを確認するためです。

AAAAAAAAAA

テストを繰り返しますが、文字列の順序を逆にして、「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進ダンプを確認します。

BBBBBBBBBB

レコードの構造が説明、レコードの固定および可変長列は別個のブロックに格納されています。固定列タイプと可変列タイプを論理的にインターリーブすることは、物理レコードに影響しません。ただし、各ブロック内では、列の順序はデータファイル内のバイトの順序にマッピングされます。

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

こちらもご覧ください:

列の順序は重要ではありませんが…一般的には、それは依存します!


+1同意します。私はいつも、各セクション内で列の順序が最初にCREATE TABLEステートメントに従っていることを発見しました(CIキー列がセクションの最初に来ることを除いて)。ただし、ALTER COLUMNデータ型/列の長さを変更すると、列の順序が変わる可能性があります。私が考えることができることを重要わずかな場合は、空の文字列またはNULLと可変長部分の末尾の列が(2008内部帳にカレン・ディレイニーによって証明)列オフセット配列内のすべてのではスペースを取らないということです
マーティンスミス

1
まれに、列の順序が重要になる場合があります。たとえば、A、B、Cの3つの列があり、それぞれの長さが3kbバイトのテーブルがある場合。SQL Serverページは8kbなので、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ショー-
Ronen氏Ariely

@RonenArielyおもしろい例ですが、元の質問のコンテキストでは多少不自然です。後で列をドロップすると、列の順序がどのように影響するかを示しています。どの列をドロップするかを先見の明を持ってテーブルを設計したことはないと思います。
マークストーリースミス

こんにちは@ MarkStorey-Smith。(1)建築家として、私はウェルデザインとグレートデザインの違いは、良いデザインが現在のニーズを提供するのに対し、グレートデザインはまだ知られていない将来のニーズを提供するということを常に説明します。(2)質問に対する答えは「はい」です。答えの実装は、OPと私たち一人一人に任されています。これは議論の範囲外ですが、議論のためにこのトピックを開くことができます。ただし、stackoverflowフォーラムファミリではありません。インターフェイスでは実際のディスカッションを許可せず、応答にテキストの短い短い行を1つだけ追加するためです
Ronen Ariely

7

クラスター化インデックスを定義しない場合、ヒープテーブルが取得されます。ヒープテーブルの場合、データの読み取り時には常にスキャンが行われるため、行全体が読み取られ、列の順序が重要なポイントになります。

クラスター化インデックスを定義するとすぐに、指定した列の物理的な順序に合わせてデータが物理的に再配置されます。この時点で、物理的な順序が重要になります。物理的な順序は、使用している述語に基づいて検索演算子の適格性を決定するものです。

どこでも読んだことを思い出せませんが、SQL Serverはヒープの列の物理的な順序を保証しないと思いますが、インデックスの場合は保証されます。あなたの質問に答えるには、いいえ、定義の列の順序は、データを読み込むときに関係ないので重要ではありません(これはヒープ専用であることに注意してください-インデックスは別の問題です)。

更新
実際には、「テーブル内の列の論理的な順序がストレージレイヤーでの物理的な順序に影響を与えるかどうか」という2つの質問をしています。メタデータによって定義される論理的な順序は、物理的な順序と同じ順序である必要はありません。答えを探しているのは、CREATE TABLEの論理的な順序が、作成時に同じ物理的な順序になるかどうかです(ヒープについてはわかりませんが)。


2

私が見たものと読んだものに基づいて、SQL Serverの列の順序に違いはありません。ストレージエンジンは、CREATE TABLEステートメントでの列の指定に関係なく、列を行に配置します。そうは言っても、それが問題になる非常に孤立したエッジケースがいくつかあると確信していますが、これらについての単一の明確な答えを得るのに苦労すると思います。ポールランダルの「ストレージエンジンの内部ブログカテゴリの投稿は、ストレージエンジンがどのように機能するかについてのすべての詳細の最良の情報源です。私の状況に当てはまる特定のエッジケースが指摘されていない限り、CREATE TABLEで列を論理的に並べるだけです。


1

意味がわかります。設計の観点から、次のような表:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

次のような表よりもはるかに優れています。

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

ただし、次のようなtsqlを発行した場合、データベースエンジンは論理列の順序を実際に気にしません。

SELECT FirstName, LastName, SSN FROM Employees

エンジンは、FirstNameのリストがディスクのどこに保存されているかを知っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.