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がクラスターインデックスシークを実行しますが、これは予想どおりです。しかし、Table Productsの場合、クラスターインデックススキャンを実行するため、疑問が生じます。 FKがクエリパフォーマンスの向上に役立たないのはなぜですか?
そのため、Products.CategoryIdにインデックスを作成する必要があります。実行プランを再度作成すると、両方のテーブルでインデックスシークが実行されます。また、推定サブツリーコストが大幅に削減されます。
私の質問は:
FKは関係の制約に役立ちますが、その他の有用性はありますか?クエリのパフォーマンスが向上しますか?
すべてのテーブルのすべてのFK列(Products.CategoryIdなど)にインデックスを作成する必要がありますか?
外部キーは参照整合性ツールであり、パフォーマンスツールではありません。少なくともSQL Serverでは、FKを作成しても関連するインデックスは作成されません。検索時間を短縮するには、すべてのFKフィールドにインデックスを作成する必要があります。
外部キーはパフォーマンスを向上させる(そして傷つける)
ここで述べたように、 外部キーはパフォーマンスを向上させます
ルックアップを減らすために、常にFK列にインデックスを作成する必要があります。 SQL Serverはこれを自動的に行いません。
編集
現在、リンクは死んでいるようです(気づいたことでChrisに拍手).
外部キー制約により、データの読み取り時のパフォーマンスが向上しますが、同時にデータの挿入/変更/削除時のパフォーマンスが低下します。
クエリを読み取る場合、オプティマイザは外部キー制約を使用して、外部キー制約が事前に宣言されたルールであるため、より効率的なクエリプランを作成できます。これには通常、クエリプランの一部をスキップする必要があります。たとえば、オプティマイザは、外部キー制約のために、プランの特定の部分を実行する必要がないことを確認できるためです。
外部キーは、データベースの整合性を確保するためのDBMSの概念です。
パフォーマンスへの影響/改善は、使用されているデータベーステクノロジーに固有のものであり、外部キーの目的に付随します。
SQL Serverでは、すべての外部キーに少なくとも非クラスター化インデックスが含まれるようにすることをお勧めします。
これで問題が解決することを願っていますが、詳細についてはお気軽にお問い合わせください。
パフォーマンスの最善の策は、頻繁に使用するフィールドでインデックスを使用することです。 SQL Serverを使用する場合、プロファイラーを使用して特定のデータベースのプロファイルを作成し、出力するファイルを取得し、チューニングウィザードを使用してインデックスの配置場所に関する推奨事項を取得できます。また、プロファイラーを使用して長時間実行されているストアドプロシージャをフラッシュするのが好きです。毎週公開する最悪の犯罪者リストのトップ10を持っています。
これを使用して、クエリをより効率的にすることができます。 SQL Serverでクエリを再構築して、内部結合ではなく外部結合を使用して、列にNULLが存在するかどうかを確認する必要があるSQLサーバーを削除できます。外部キーの関係が既にそれを強制しているので、その修飾子を入れる必要はありません。
したがって、この:
select p.ProductId, p.Name, c.CategoryId, c.Name AS Category
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere 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;
これにより、小さなクエリで必ずしも大きなパフォーマンスが得られるとは限りませんが、テーブルが大きくなると、より効率的になります。
テーブルに外部キーを追加してもパフォーマンスは向上しません。ProductCategoriesテーブルデータベースにレコードを挿入する場合、製品テーブルのプライマリキー値に存在する値を持つ外部キー列を見つけようとすると、このルックアップ、 ProductCategoriesテーブルに新しいエントリを追加するたびに、データベースでの操作がオーバーヘッドになります。したがって、外部キーを追加してもデータベースのパフォーマンスは向上しませんが、データベースの整合性は考慮されます。はい、プログラムのデータベースにレコードが存在することを確認するために多くのクエリを実行する代わりに、外部キーを使用して整合性を確認する場合、dbのパフォーマンスが向上します。
MySQL 5.7では、複数の結合を含むクエリを驚くほど高速に実行できます。
「explain」を使用してクエリを理解したところ、キーがまったく使用されていない4〜5個のテーブルを結合していることがわかりました。これらのテーブルに外部キーを追加するだけで、ロード時間は90%短縮されました。 5秒以上かかったクエリの所要時間は500ミリ秒以下になりました。
それは途方もない改善です!
そして、他の人が述べたように、あなたは関係の完全性を保証するという追加のボーナスを受け取ります。
これ以外に、参照整合性を保証することには、パフォーマンス上の利点もあります。外部キーを持つテーブルが外部テーブルで「最新」であることを保証するという2次効果があります。たとえば、ユーザーテーブルとコメントテーブルがあり、コメントテーブルで統計を行っているとします。おそらく、ユーザーを完全に削除した場合、ユーザーのコメントも不要になります。
SQL Server 2008の時点では、データベースエンジンがクエリの最適化を選択する方法に影響を与えることにより、外部キーがパフォーマンスに影響を与える可能性があります。次の記事のStar Join Heuristicsを参照してください。 https://technet.Microsoft.com/en-us/library/2008.04.dwperformance.aspx
SQLサーバーについてはあまり知りませんが、Oracleの場合、外部キー列があるとデータのロードのパフォーマンスが低下します。これは、データベースが各挿入のデータ整合性をチェックする必要があるためです。はい、既に述べたように、外部キー列にインデックスを作成することは良い習慣です。