次のSQLステートメントはTable1.Table1Columnにインデックスを自動的に作成しますか、それとも明示的に作成する必要がありますか?
データベースエンジンはSQL Server 2000です
CREATE TABLE [Table1] (
. . .
CONSTRAINT [FK_Table1_Table2] FOREIGN KEY
(
[Table1Column]
) REFERENCES [Table2] (
[Table2ID]
)
)
SQL Serverは、外部キーにインデックスを自動的に作成しません。またMSDNから:
FOREIGN KEY制約は、別のテーブルのPRIMARY KEY制約にのみリンクする必要はありません。別のテーブルのUNIQUE制約の列を参照するように定義することもできます。 FOREIGN KEY制約にはnull値を含めることができます。ただし、複合FOREIGN KEY制約の列にNULL値が含まれている場合、FOREIGN KEY制約を構成するすべての値の検証はスキップされます。複合FOREIGN KEY制約のすべての値が検証されるようにするには、関与するすべての列にNOT NULLを指定します。
マイクの質問を読んだとき、彼はFK ConstraintがFKが入っているテーブル(Table1)のFK列にインデックスを作成するかどうかを尋ねています。答えはノー、そして一般的です。 (制約の目的上)、これを行う必要はありません。一方、制約の「ターゲット」として定義された列は、参照されるテーブルの一意のインデックスであるか、主キーである必要があります。または代替キー。 (一意のインデックス)または制約の作成ステートメントは失敗します。
(編集:以下のコメントを明示的に処理するために追加-)具体的には、外部キー制約が存在するデータの一貫性を提供する場合。インデックスは、FK側の行の削除に対してのみ、DRI制約のパフォーマンスに影響を与える可能性があります。制約を使用する場合、挿入または更新中にプロセッサはFK値を認識し、PK側の参照先テーブルに行が存在するかどうかを確認する必要があります。すでにインデックスがあります。 PK側の行を削除する場合、FK側に行がないことを確認する必要があります。この場合、インデックスはわずかに役立ちます。しかし、これは一般的なシナリオではありません。
ただし、特定の種類のクエリでは、クエリプロセッサが、その外部キー列を使用する結合の多くの側でレコードを見つける必要がある場合があります。結合パフォーマンスisは、その外部キーにインデックスが存在する場合に増加します。ただし、この条件は、外部キー制約の存在ではなく、結合クエリでのFK列の使用に固有です...結合の反対側がPKであるか、他の任意の列であるかは関係ありません。また、そのFK列に基づいてクエリの結果をフィルタリングまたは順序付ける必要がある場合は、インデックスが役立ちます...繰り返しますが、これはその列の外部キー制約とは関係ありません。
いいえ、列に外部キーを作成しても、その列にインデックスは自動的に作成されません。外部キー列のインデックス付けに失敗すると、次の各状況でテーブルスキャンが発生します。
このスキーマ例では:
CREATE TABLE MasterOrder (
MasterOrderID INT PRIMARY KEY)
CREATE TABLE OrderDetail(
OrderDetailID INT,
MasterOrderID INT FOREIGN KEY REFERENCES MasterOrder(MasterOrderID)
)
OrderDetailは、MasterOrderテーブルでレコードが削除されるたびにスキャンされます。 OrderMasterとOrderDetailを結合するたびに、OrderDetailテーブル全体もスキャンされます。
SELECT ..
FROM
MasterOrder ord
LEFT JOIN OrderDetail det
ON det.MasterOrderID = ord.MasterOrderID
WHERE ord.OrderMasterID = @OrderMasterID
一般に、外部キーのインデックスを作成しないことは、ルールよりもはるかに例外です。
外部キーのインデックスを作成しないのは、外部キーが使用されない場合です。これにより、サーバーを維持するオーバーヘッドが不要になります。型テーブルは時々このカテゴリに分類されます。例は次のとおりです。
CREATE TABLE CarType (
CarTypeID INT PRIMARY KEY,
CarTypeName VARCHAR(25)
)
INSERT CarType .. VALUES(1,'SEDAN')
INSERT CarType .. VALUES(2,'COUP')
INSERT CarType .. VALUES(3,'CONVERTABLE')
CREATE TABLE CarInventory (
CarInventoryID INT,
CarTypeID INT FOREIGN KEY REFERENCES CarType(CarTypeID)
)
CarType.CarTypeIDフィールドは決して更新されず、レコードの削除はほとんど行われないという一般的な仮定を行うと、CarInventoryがCarTypeIDで検索されなかった場合、CarInventory.CarTypeIDのインデックスを維持するサーバーオーバーヘッドは不要になります。