4

次のようなクエリがあります。

SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE ISNULL(t1.DeleteFlag,'N') = 'N'

パーツのインデックス シークが発生するはずのインデックスが配置されています= 'N'が、代わりに非常にコストのかかるインデックス スキャンが発生しています。インデックスがインデックスの正しい使用法を台無しにしている可能性はありますか? (will のように) 少数の可能な値しか持たない列にインデックスを付けることは理にかなっていますDeleteFlagか?

4

3 に答える 3

9

はい、WHERE 句で関数を呼び出すと、インデックスが役に立たなくなる可能性があります。インデックスを使用できるように書き直してみてください。

SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE NOT t1.DeleteFlag = 'Y'

クエリから期待される結果の数が、テーブル内の行の総数よりもはるかに少ない場合、インデックスは意味があります。

于 2009-12-22T22:24:14.963 に答える
8

Mark Byers の答えは機能しません。これは、SQL Server が null を処理する非常に微妙な方法によるものです。WHERE 式 " t1.DeleteFlag = 'Y' " で、t1.DeleteFlag が NULL の場合、式は NULL を返します。したがって、NOT (NULL) を実行しても NULL が返され、これは WHERE 条件に失敗します。このテストを実行してみてください:

DECLARE @myvar VARCHAR(1)
SET @myvar = NULL

SELECT 'OK' WHERE ISNULL(@myvar, 'N') = 'N' -- Baseline statement. Returns OK
SELECT 'OK' WHERE NOT (@myvar = 'Y')        -- Equivalent to answer above. Fails
SELECT 'OK' WHERE @myvar = 'N' OR @myvar IS NULL -- This is another way to do it. Also returns OK

2 番目の select ステートメントは行を返さないため、baseline ステートメントと同等ではなく、機能しません。3 番目のステートメントは、このクエリを作成する別の方法です。1 つは機能し、2 つはフィールドのインデックスを使用できることを保証します。

したがって、これが質問に対する正しい答えです。

SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE (t1.DeleteFlag = 'N' OR t1.DeleteFlag IS NULL)

おそらく名目上はより良いパフォーマンス結果が得られるこれに代わる方法は、DeleteFlag フィールドを「NOT NULL」として定義し、DEFAULT として '' (空の文字列) を指定することです。次に、クエリは NULL を気にせずに簡単に記述できます。

SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE t1.DeleteFlag = 'N'
于 2012-12-29T00:45:32.893 に答える
8

1) ISNULL を使用すると、シークがスキャンに変わりますか? はい。一般に、列に関数を適用すると、式が SARG 不可 (検索不可) になります。インデックスが Seek 操作の対象と見なされるためには、エンジンはシークする値を生のバイナリ値として認識している必要があります。関数を列に適用するとすぐに、関数の結果を検索するように求めているため、すべての行で関数を評価して、結果が条件を満たしているかどうかを確認する必要があります。

2) 選択性が非常に低い列 (2 ~ 3 つの値) にインデックスを設定することは理にかなっていますか? はい。ただし、スタンドアロンのインデックス式としては使用できません。インデックスの転換点により、選択性の低い列のスタンドアロン インデックスはスペースの無駄になります。ただし、ビットやフラグなどの非常に選択性の低い列は、より多くのキーで構成されている場合、インデックスの左端のキーとして非常に役立ちます。あなたの場合、それが削除されたフラグであることを考えると、すべてのクエリが「IsDeleted」条件を指定することが期待されるため、クラスター化インデックスの最初のキーになることは理にかなっています。

また、おそらく「削除済み」フラグに NULL を含めるべきではないことも付け加えておきます。

于 2009-12-22T22:40:37.083 に答える