web-dev-qa-db-ja.com

外部キーにインデックスを作成する必要がありますか?

テーブルAとテーブルBがあります。 Aには、Bの主キーB_ID上のBへの外部キーがあります。

何らかの理由(正当な理由があることを知っています)で、キーでこれら2つのテーブルを結合するときにインデックスを使用していません。

A.B_IDに個別にインデックスを作成する必要がありますか、または外部キーの存在がそれを提供する必要がありますか?

109
aw crud

外部キー制約だけではインデックスは提供されません-作成する必要があります(作成する必要があります)。

124
DCookie

外部キーを作成しても、A.B_IDにインデックスは自動的に作成されません。したがって、クエリパフォーマンスの観点からは、A.B_IDに個別のインデックスを作成するのが一般的に理にかなっています。

Bの行を削除した場合、A.B_IDにインデックスを作成する必要があります。そうしないと、孤立したレコードがないことを確認するために、Bから行を削除するたびにAで全テーブルスキャンを実行する必要があります(Oracleのバージョンによっては、追加のロックへの影響もありますが、それらは減少します)より新しいOracleバージョンで)。

42
Justin Cave

詳細については、(a)制約を強制する必要がないため、および(b)場合によっては必要ないため、Oracleはインデックスを自動的に作成しません(一意の制約の場合と同様)。

ほとんどただし、インデックスを作成する必要があります(実際、Oracle Apexには「インデックスなし外部キー」のレポートがあります)。

アプリケーションが親テーブルの行を削除したり、PK値を更新する必要がある(まれですが)必要があるときはいつでも、インデックスが存在しない場合、子テーブル全体をロックする必要があるため、DMLが影響を受けます。

通常、インデックスを追加するためにnotを選択する場合は、FKが列のドメイン(ステータスコードのテーブルなど)を定義する「静的データ」テーブルにあり、更新と削除が行われる場合です。親テーブルでは、アプリケーションによって直接実行されることはありません。ただし、列にインデックスを追加すると、アプリケーション内の重要なクエリにメリットがもたらされる場合は、インデックスを使用することをお勧めします。

23
Jeffrey Kemp

SQL Serverは、インデックスを外部キー列に自動的に配置したことはありません。この都市の神話の背景と歴史について、Kim Trippの excellent blog post をチェックしてください。

ただし、通常は外部キー列にインデックスを付けることをお勧めします。したがって、はい、各FK列がインデックスによってバックアップされていることを確認することをお勧めします。必ずしもその1つの列だけでなく、2つまたは3つの列にインデックスを作成して、そこの最初の列としてFK列を作成することもできます。シナリオとデータに依存します。

12
marc_s

パフォーマンス上の理由から、インデックスを作成する必要があります。プライマリテーブルの削除操作(削除するレコードが使用されていないことを確認するため)および通常外部キーが関係する結合で使用されます。インデックスを必要としないテーブルはわずかしかありません(ログに作成しません)が、おそらくこの場合、外部キー制約も必要ないでしょう。

しかし

外部キーのインデックスをすでに自動的に作成するデータベースがいくつかあります。ジェットエンジン(Microsoft Accessファイル)Firebird MySQL

確かに

SQL Server Oracle

ではない

6
bubi

パフォーマンスに関連するものと同様に、それは多くの要因に依存しており、特効薬はありません。非常に高度な環境では、インデックスの維持は受け入れられない可能性があります。

ここで最も顕著なのは選択性のようです。インデックス内の値が非常に重複している場合、インデックスを削除し(可能な場合)、テーブルスキャンを許可するとパフォーマンスが向上する可能性があります。

1
onedaywhen