161

Products と ProductCategories の 2 つのテーブルがあるとします。両方のテーブルには、CategoryId に関する関係があります。そして、これがクエリです。

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

実行計画を作成すると、テーブル ProductCategories はクラスター インデックス シークを実行しますが、これは期待どおりです。しかし、テーブル Products については、クラスター インデックス スキャンを実行するので、疑問に思います。FK がクエリのパフォーマンスの向上に役立たないのはなぜですか?

したがって、Products.CategoryId にインデックスを作成する必要があります。実行計画を再度作成すると、両方のテーブルでインデックス シークが実行されます。また、推定サブツリーのコストが大幅に削減されます。

私の質問は次のとおりです。

  1. FK は関係の制約に役立ちますが、それ以外に役立つことはありますか? クエリのパフォーマンスは向上しますか?

  2. すべてのテーブルのすべての FK 列 (Products.CategoryId など) にインデックスを作成する必要がありますか?

4

10 に答える 10

202

外部キーは参照整合性ツールであり、パフォーマンス ツールではありません。少なくとも SQL Server では、FK を作成しても関連するインデックスは作成されません。ルックアップ時間を改善するには、すべての FK フィールドにインデックスを作成する必要があります。

于 2009-02-03T14:07:29.060 に答える
65

外部キーはパフォーマンスを向上させる (そして損なう) 可能性があります

  1. ここで述べたように:外部キーがパフォーマンスを向上させます

  2. ルックアップを減らすために、常に FK 列にインデックスを作成する必要があります。SQL Server はこれを自動的に行いません。

編集

リンクが死んでいるように見えるので(Chris に気づいてくれたことを称賛します)、以下は外部キーがなぜパフォーマンスを向上させる (そして傷つける) ことができるのかという要点を示しています。

外部キーはパフォーマンスを向上させることができますか

外部キー制約は、データの読み取り時のパフォーマンスを向上させますが、同時にデータの挿入/変更/削除時のパフォーマンスを低下させます。

外部キー制約は事前に宣言されたルールであるため、クエリを読み取る場合、オプティマイザは外部キー制約を使用してより効率的なクエリ プランを作成できます。これには通常、クエリ プランの一部をスキップすることが含まれます。たとえば、オプティマイザーは、外部キー制約のためにプランの特定の部分を実行する必要がないことを確認できるためです。

于 2009-02-03T14:14:07.390 に答える
18

外部キーは、データベースの整合性を確保するための DBMS の概念です。

パフォーマンスへの影響/改善は、使用されているデータベース テクノロジに固有のものであり、外部キーの目的の二次的なものです。

SQL Server では、すべての外部キーに少なくとも非クラスター化インデックスがあることを確認することをお勧めします。

これで問題が解決することを願っていますが、お気軽に詳細をリクエストしてください。

于 2009-02-03T14:10:34.310 に答える
4

最善のパフォーマンスの賭けは、頻繁に使用するフィールドにインデックスを使用することです。SQL Server を使用している場合は、プロファイラーを使用して特定のデータベースをプロファイリングし、出力されたファイルを取得して、チューニング ウィザードを使用して、インデックスを配置する場所に関する推奨事項を受け取ることができます。また、プロファイラーを使用して長時間実行されているストアド プロシージャをフラッシュするのも好きです。毎週公開する最悪の犯罪者のトップ 10 リストを持っており、人々を正直に保ちます :D.

于 2009-02-03T15:02:27.607 に答える
3

SQL Serverについてはよくわかりませんが、Oracleの場合、外部キー列があるとデータ読み込みのパフォーマンスが低下します。これは、データベースが挿入ごとにデータの整合性をチェックする必要があるためです。そして、はい、すでに述べたように、外部キー列にインデックスを付けることは良い習慣です。

于 2009-02-03T15:09:52.927 に答える
3

テーブルに外部キーを追加してもパフォーマンスは向上しません。ProductCategoriesテーブルデータベースにレコードを挿入する場合、外部キー列が製品テーブルの主キー値に存在する値を見つけようとするだけです。このルックアップ、 ProductCategoriesテーブルに新しいエントリを追加するたびに、データベースの操作はオーバーヘッドになります。したがって、外部キーを追加してもデータベースのパフォーマンスは向上しませんが、データベースの整合性は考慮されます。はい、レコードがプログラムのデータベースに存在することを確認するために多くのクエリを実行する代わりに、外部キーを使用して整合性を確認している場合、dbのパフォーマンスが向上します。

于 2011-08-28T09:43:07.560 に答える
3

これを使用して、クエリをより効率的にすることができます。内部結合の代わりに外部結合を使用するように SQL Server でクエリを再構築できるため、SQL サーバーで列に null があるかどうかを確認する必要がなくなります。外部キー関係がすでにそれを強制しているため、その修飾子を入れる必要はありません。

したがって、この:

select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p
inner join ProductCategories c on
p.CategoryId = c.CategoryId
where c.CategoryId = 1;

これになります:

 SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
 FROM ProductCategories c 
 LEFT OUTER JOIN Products P ON
 c.CategoryId = p.CategoryId 
 WHERE c.CategoryId = 1;

これは、小さなクエリでは必ずしも大きなパフォーマンスを発揮するとは限りませんが、テーブルが大きくなると、より効率的になります。

于 2009-02-03T14:15:42.100 に答える
2

MySQL 5.7 の場合、複数の結合を含むクエリを驚くほど高速化できます!

「explain」を使用してクエリを理解したところ、キーがまったく使用されていない 4 ~ 5 個のテーブルを結合していることに気付きました。これらのテーブルに外部キーを追加しただけで、読み込み時間が 90% 短縮されました。5 秒以上かかっていたクエリが 500 ミリ秒以下になりました。

それは非常に大きな改善です!

そして、他の人が述べたように、関係の整合性を確保するという追加のボーナスが得られます.

これ以外にも、参照整合性の確保には独自のパフォーマンス上の利点もあります。外部キーを持つテーブルが外部テーブルで「最新」であることを保証するという2次効果があります。ユーザー テーブルとコメント テーブルがあり、コメント テーブルで統計を行っているとします。おそらく、ユーザーを完全に削除すると、そのユーザーのコメントも不要になります。

于 2018-06-18T22:03:59.660 に答える