Thật không may, dường như không có cách nào để tạo bộ lọc âm cho một chỉ mục, mà không dùng đến việc tạo ra một khung nhìn cụ thể hóa. Nếu nó đã có thể tạo ra một bộ lọc tiêu cực như một trong những bạn muốn, nó sẽ là khá khó khăn đối với các truy vấn tối ưu hóa để "nhặt" các chỉ số để sử dụng, tăng đáng kể thời gian cần thiết để tìm ra một kế hoạch tốt.
Tùy thuộc vào các mẫu truy vấn cho bảng này, bạn có thể chỉ cần tạo hai chỉ mục; một cho ít hơn 9 và một cho lớn hơn 14. Một trong hai chỉ mục này có thể được chọn bởi trình tối ưu hóa truy vấn cho WHERE
các mệnh đề đơn giản như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);
Một cách khác để thực hiện điều này có thể là:
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);
Điều này sử dụng chỉ mục được lọc từ 9 đến 14 để loại trừ các hàng.
Trong thử nghiệm của tôi, một chỉ số bao phủ đơn giản trả về các hàng nhanh nhất:
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);
Ngoài ra, sử dụng một biến thể của cách tiếp cận được sử dụng trong câu trả lời của riêng bạn :
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;
Mặc dù bộ lọc được viết dưới dạng liên từ, nó hỗ trợ các truy vấn được viết theo bất kỳ cách nào sau đây (cách đầu tiên hiệu quả hơn một chút):
StatusID NOT IN (9, 10, 11, 12, 13, 14)
StatusID < 9 OR StatusID > 14
StatusID NOT BETWEEN 9 AND 14