Chúng ta hãy ném một triệu hàng vào một bảng tạm thời cùng với một vài cột:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (PK)
);
INSERT INTO #174860 WITH (TABLOCK)
SELECT RN
, RN % 1000
, RN % 10000
FROM
(
SELECT TOP 1000000 ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values v1,
master..spt_values v2
) t;
CREATE INDEX IX_174860_IX ON #174860 (COL1) INCLUDE (COL2);
Ở đây tôi có một chỉ mục cụm (theo mặc định) trên PK
cột. Có một chỉ mục không bao gồm trên COL1
đó có một cột chính COL1
và bao gồm COL2
.
Hãy xem xét các truy vấn sau:
SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;
Ở đây tôi không sử dụng BETWEEN
vì Aaron Bertrand đang lảng vảng câu hỏi này.
SQL Server nên tối ưu hóa truy vấn đó như thế nào? Chà, tôi biết rằng bộ lọc trên PK
sẽ giảm kết quả được đặt thành năm hàng. Máy chủ SQL có thể sử dụng chỉ mục được nhóm để nhảy đến năm hàng đó thay vì đọc qua tất cả hàng triệu hàng trong bảng. Tuy nhiên, chỉ mục cụm chỉ có cột PK là cột chính. Khi hàng được đọc vào bộ nhớ, chúng ta cần áp dụng bộ lọc trên COL2
. Ở đây, PK
là một vị ngữ tìm kiếm và COL2
là một vị ngữ.
Máy chủ SQL tìm thấy năm hàng bằng cách sử dụng vị từ tìm kiếm và tiếp tục giảm năm hàng đó thành một hàng với vị từ thông thường.
Nếu tôi xác định chỉ mục cụm khác nhau:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);
Và chạy cùng một truy vấn tôi nhận được kết quả khác nhau:
Trong trường hợp này, SQL Server có thể tìm kiếm bằng cách sử dụng cả hai cột trong WHERE
mệnh đề. Chính xác một hàng được đọc từ bảng bằng các cột chính.
Để biết thêm một ví dụ, hãy xem xét truy vấn này:
SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;
Chỉ mục IX_174860_IX là chỉ mục bao phủ vì nó chứa tất cả các cột cần thiết cho truy vấn. Tuy nhiên, chỉ COL1
là một cột quan trọng. SQL Server có thể tìm kiếm với cột đó để tìm 1000 hàng có COL1
giá trị khớp . Nó có thể lọc thêm các hàng trên COL2
cột để giảm kết quả cuối cùng được đặt thành 0 hàng.