2008-08-28 10 views
21

と協力ください:は、インデックスが「IN」句

Select EmployeeId 
From Employee 
Where EmployeeTypeId IN (1,2,3) 

と私はEmployeeTypeIdフィールドにインデックスを持って、SQLサーバーは、まだそのインデックスを使用していますか?

+2

なぜこれは本当の質問ではないのですか? – nawfal

+0

どちらか?これは私がソートをしようとするためにここに来たのとまったく同じ質問で、それは私に仕事のための素晴らしい情報を与えました。 –

+0

+1の@nawfal - 私も同じように感じます。 –

答えて

13

はい、そうです。従業員表に10,000レコードがあり、5レコードだけが(1,2,3)にemployeetypeIDを持つ場合、索引を使用してレコードをフェッチする可能性が最も高くなります。しかし、9,000のレコードのemployeeIDTypeが(1,2,3)であることがわかった場合は、表全体を実行するよりも速いため、対応するEmployeeIDを取得するためにテーブルスキャンを実行する可能性が最も高いでしょうインデックスツリーの各ブランチを開き、レコードを個別に調べます。

SQL Serverは、クエリの実行方法を最適化しようとするには、多くのことがあります。しかし、正しい答えが得られないことがあります。 SQL Serverがインデックスを使用していないことがわかっている場合は、クエリアナライザで実行プランを調べることで、クエリに次の変更を加えて特定のインデックスを使用するようにクエリエンジンに指示できます。

EmployeeTypeIdフィールド上のあなたが持っているインデックスがIndex_EmployeeTypeId命名されたと仮定すると、
Select EmployeeId From Employee WITH (Index(Index_EmployeeTypeId)) Where EmployeeTypeId IN (1,2,3) 

4

通常、IN節がテーブルのあまりに多くをカバーしない限り、それはテーブルスキャンを行います。特定のケースでは、クエリアナライザで実行し、実行計画をチェックするのが最適な方法です。

2

だから、テーブルスキャンを実行するには、「IN」句の可能性がありますが、オプティマイザは それに対処するための最良の方法を試してみて、うまくいきますか?

インデックスを使用するかどうかは、テーブル内のデータの種類と分布、クエリの統計情報の最新の状態、列の実際のデータ型

場合、他のポスターは、インデックスは、テーブルスキャン上で使用されることが適切である:クエリが(たとえば〜10%インデックス付きの列の一定割合以上にアクセスしませんが、変化すべきである

  • DBMSの間)。
  • また、列に多数の行がありますが、列に固有の値が比較的少ない場合は、表スキャンを実行する方が高速かもしれません。

明白ではない他の変数は、比較される値のデータ型が同じであることを確認することです。 PostgreSQLでは、floatでフィルタリングしているのにカラムがintで構成されている場合、インデックスは使用されないと思います。インデックスの使用をサポートしていない演算子もあります(PostgreSQLでは、ILIKE演算子はこのようになります)。

ご存知のように、疑問やDBMSのドキュメントがあなたの友人である場合は、常にクエリアナライザをチェックしてください。

3

技術が改善されていない限り、「IN」クエリは結果として3つの結果セットのOR演算を効果的に行います。リスト。 IN節は各リストの等価条件になり、必要に応じてインデックスを使用します。一意のIDと十分な大きさのテーブルの場合は、オプティマイザがインデックスを使用することが期待されます。

リストの項目は、しかし、非一意であることだった、と私は「型IDは」外部キーであることを例に推測している場合、私は、分布のより興味があります。オプティマイザがリストの各値の統計をチェックするかどうか疑問に思っていますか?それが最初の値をチェックし、20%の行(問題となる十分な大きさのテーブル)にあることを確認します。おそらくテーブルスキャンでしょう。しかし、他の2つのクエリプランが同じであっても、同じクエリプランを使用することはできますか?

Employeeテーブルのように、メモリにキャッシュされたままになるほど小さく、おそらくそれとインデックス取得の違いに気づかないようなものです。

最後に、私が説教している間、IN節でクエリを覚えておいてください:何かを働かせるための迅速な方法です(少なくとも私にとっては)要件を表現する良い方法ですが、常に結合として再表示されます。あなたのオプティマイザは、これを発見するのに十分なほどスマートになるかもしれませんが、そうではないかもしれません。現在、運用データボリュームに対してパフォーマンスチェックを行っていない場合は、そのようにします。コストベースの最適化の最近の段階では、完全な負荷と代表的な統計が得られるまで、クエリプランを確認することはできません。あなたは、それから...生産の驚きのために準備することができない場合は

1

@マイク:詳細な分析をありがとう。あなたがそこで作る興味深い点は間違いありません。私が投稿した例はやや簡単ですが、この問題の根拠はNHibernateの使用に由来しています。

NHibernateのでは

、あなたがこのような句を書くことができます:

int[] employeeIds = new int[]{1, 5, 23463, 32523}; 
NHibernateSession.CreateCriteria(typeof(Employee)) 
.Add(Restrictions.InG("EmployeeId",employeeIds)) 
NHibernateのは、あなたと他の人が指摘しているように、それはそこにのように見える

select * from employee where employeeid in (1, 5, 23463, 32523) 

のように見えるのクエリを生成し

インデックスが使用されるか、テーブルスキャンが実行される時間になりますが、実行時までそれを決定することはできません。

0
Select EmployeeId From Employee USE(INDEX(EmployeeTypeId)) 

このクエリは、作成したインデックスを使用して検索します。わたしにはできる。試してみてください。