残念ながら、マテリアライズドビューの作成に頼らずにインデックスの否定フィルターを作成する方法はないようです。希望するフィルターなどの否定的なフィルターを作成することができた場合、クエリオプティマイザーが使用するインデックスを "選択"することは非常に難しく、適切なプランを見つけるために必要な時間が大幅に増加します。
このテーブルのクエリパターンに応じて、単純に2つのインデックスを作成できます。これらのインデックスの14いずれか未満9と大きいための1つのための1つができる単純なため、クエリ・オプティマイザによって選択されるWHERE
ような条項WHERE StatusID = 6
CREATE TABLE dbo.TestNegativeFilter
(
TestNegativeFilter INT NOT NULL
CONSTRAINT PK_TestNegativeFilter
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, StatusID INT NOT NULL
);
GO
CREATE INDEX IX_TestNagativeFilter_LessThan9
ON dbo.TestNegativeFilter(StatusID)
WHERE (StatusID < 9);
CREATE INDEX IX_TestNagativeFilter_GreaterThan14
ON dbo.TestNegativeFilter(StatusID)
WHERE (StatusID > 14);
これを実現する別の方法は次のとおりです。
CREATE INDEX IX_TestNegativeFilter_9_to_14
ON dbo.TestNegativeFilter(StatusID)
WHERE (StatusID IN (9, 10, 11, 12, 13, 14));
SELECT *
FROM dbo.TestNegativeFilter tnf
EXCEPT
SELECT *
FROM dbo.TestNegativeFilter tnf
WHERE tnf.StatusID IN (9, 10, 11, 12, 13, 14);
これは、行を除外するために9から14でフィルタリングされたインデックスを使用します。
私のテストリグでは、単純なカバリングインデックスが行を最も速く返します。
CREATE NONCLUSTERED INDEX IX_TestNegativeFilter_StatusID
ON dbo.TestNegativeFilter(StatusID)
INCLUDE (TestNegativeFilter);
SELECT *
FROM dbo.TestNegativeFilter tnf
WHERE tnf.StatusID NOT IN (9, 10, 11, 12, 13, 14);
あるいは、あなた自身の答えで使用されているアプローチのバリエーションを使用してください:
CREATE INDEX [IX dbo.TestNegativeFilter StatusID not 9-14]
ON dbo.TestNegativeFilter (StatusID)
WHERE StatusID <> 9
AND StatusID <> 10
AND StatusID <> 11
AND StatusID <> 12
AND StatusID <> 13
AND StatusID <> 14;
フィルタは論理積として記述されていますが、次のいずれかの方法で記述されたクエリをサポートしています(最初の方が少し効率的です)。
StatusID NOT IN (9, 10, 11, 12, 13, 14)
StatusID < 9 OR StatusID > 14
StatusID NOT BETWEEN 9 AND 14