2013-11-22 15 views
6

SQL Server 2008を使用しており、計算列をカバーするインデックスのシークを実行することを拒否しています。SQL Serverが計算列を使用してインデックスシークを実行しない理由

私のテーブルには、次のようになります。

CREATE TABLE Person 
{ 
    Id uniqueidentifier NOT NULL, 
    InsertDate datetime NOT NULL, 
    PhoneNumber NULL, 
    PhoneNumberComparable AS (MakePhoneNumberComparable(PhoneNumber)) PERSISTED, 
    ... etc... 
} 

もクラスタ化された主キーのID列のインデックス、およびInsertDate列に索引があります。このようなPhoneNumberComparable計算列に索引がある

CREATE NONCLUSTERED INDEX IX_Person_PhoneNumberComparable ON Person 
(
    PhoneNumberComparable ASC 
) 

インデックスは、すべての日付の統計情報まで持っています。

私のクエリは次のようになります。デフォルトでは

SELECT TOP 20 * FROM Person 
WHERE PhoneNumberComparable = @PhoneNumber 
ORDER BY InsertDate DESC 

、SQL Serverは非常にパフォーマンスの低下を引き起こし、InsertDate上のインデックスの代わりに、PhoneNumberComparableのインデックスを使用することを決定しました。

WITH(INDEX = IX_Person_PhoneNumberComparable)をクエリに追加することにより、電話番号インデックスを強制的に使用しようとすると、SQLはシークではなくスキャンを実行しようとします。

私はFORCESEEKクエリヒントを使用しようとすると、SQL Serverは私に次のエラー与える:SQL Serverが私のインデックスを求めて拒否しているいくつかの理由のために、したがって、基本的

Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using SET FORCEPLAN.

を!どうして?コメントで提案を1として

EDIT

、(主キーのスキャンが実行代わりの電話番号のインデックスに求めている)私は、クエリを簡素化しましたが、問題がまだ存在します。

SELECT TOP 20 PhoneNumberComparable FROM Person 
WHERE PhoneNumberComparable = @PhoneNumber 
+0

クエリから「ORDER BY InsertDate DESC」を削除するとどうなりますか? – iruvar

+0

@ 1_CR ORDER BY InsertDate DESCをドロップすると、主キー索引の使用が試行されます。同じ問題! – cbp

+0

このスレッドではこれと似た問題について話しています。これはSQL Server 2008のバグであることを暗示しています。http://www.sqlservercentral.com/Forums/Topic1085414-392-1.aspx – cbp

答えて

5

私はこれを考え出したと思います。

問題は、MakePhoneNumberComparable関数が異なるスキーマの下にある別の関数を使用しているためです。問題を解決するには、他の関数の2番目のコピーをクローンする必要がありましたが、テーブルと同じスキーマの下に移動する必要がありました。

This article(コメント者Kahnのおかげで) "計算された列のすべての関数参照がテーブルと同じ所有者を持つ"場合のみ、インデックスを定義できます。

まあ、に付着する非常に迷惑、この所有権の要件であるだけでなく、Microsoftのドキュメントには、少なくとも言うことは非常に紛らわしいです:

  • まず、私はインデックスを作成することができます。実際、私はインデックスをスキャンすることさえできました。インデックスにシークを実行するSQLを取得できませんでした。
  • 第二に、わたしが知っている限り、私たちは所有者ではなく、ここでスキーマについて話していますが、両者の違いについて私はまだ幾分混乱しています。
  • 第3に、私の関数は、私のテーブルと同じスキーマででした。それはテーブルと同じスキーマにない2番目の関数を使用しただけです。
関連する問題