2011-07-07 10 views
6

ワークフローという名前のテーブルがあります。それには37Mの行があります。 ID列(int)にはプライマリキーと追加の列があります。 ID列は索引の最初の列です。クエリで特定のインデックスが使用されないのはなぜですか?

私は次のクエリを実行する場合(Iインデックスヒントを使用しない限り)、PKを使用しない

Select Distinct(SubID) From Workflow Where ID >= @LastSeenWorkflowID 

Iの代わりにこのクエリを実行すると、PKは

Select Distinct(SubID) From Workflow Where ID >= 786400000 

使用されるIクエリでパラメータ値を使用することで問題が発生していると思われます(これを行う必要があります)。私は本当にインデックスヒントを使いたくありません。このための回避策はありますか?あなたのPKを想定し

+0

どのSQL Serverのバージョン? –

+0

これはノンクラスタード・インデックスですか?クラスタード・インデックスはありますか? – JNK

+0

@JNK - SQL Server 2008とPKはクラスタ化インデックスです –

答えて

3

すべてのインデックスを含む正確なテーブル定義と同様に、実行計画を投稿してください。

変数を使用すると、オプティマイザはクエリの選択性を認識しません。@LastSeenWorkflowIDは、ワークフロー内の最後の行を除くすべての行を除外するか、すべてを含めることができます。生成された計画は、両方の状況で動作する必要があります。クラスタ化されたインデックスの範囲が非常に広く(リーフレベルのすべての列を含むため)、単純にクラスタ化されたインデックスが完全にスキャンされるよりも高価になるしきい値があります。繰り返し処理するページがはるかに多くなります。 @LastSeenWorkflowIDの未知の値を考慮する生成された計画は、クラスタード・インデックス・シークのコストを見積もる際にそのしきい値を超えている可能性が高く、クラスター化されていないインデックスに対してスキャンを選択します。

CREATE INDEX WorkflowSubId ON Workflow(ID) INCLUDE (SubId); 

このようなインデックスはありません、あまりにも良いツーパスクエリのです:

CREATE INDEX WorkflowSubId ON Workflow(ID, SubId); 

か:

あなたは、このクエリで特異的に目指しているの狭いインデックスを提供することができ@LastSeenWorkflowIDの値に関係します。

2

がアイデンティティであるか、常に0より大きいあなたはこの試みることができる、おそらく:第二の条件を追加することにより

Select Distinct(SubID) 
From Workflow 
Where ID >= @LastSeenWorkflowID 
    And ID > 0 

を、それがオプティマイザが求めるインデックスを使用することがあります。

0

これは、準最適な計画を作成するローカル変数の古典的な例です。

IDの実際のパラメータ値を使用してクエリをコンパイルするには、OPTION(RECOMPILE)を使用する必要があります。

詳細については、私のブログの記事を参照してください: http://www.sqlbadpractices.com/using-local-variables-in-t-sql-queries/

関連する問題