Закинемо один мільйон рядків у темп-таблицю разом з кількома стовпцями:
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);
Тут у мене є кластерний індекс (за замовчуванням) на PK
стовпці. Існує некластеризований індекс, COL1
який має ключовий стовпець COL1
і включає COL2
.
Розглянемо наступний запит:
SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;
Тут я не користуюся, BETWEEN
тому що Аарон Бертран висить навколо цього питання.
Як слід оптимізувати SQL Server для запиту? Ну, я знаю, що включений фільтр PK
зменшить набір результатів до п'яти рядків. Сервер SQL може використовувати кластерний індекс, щоб перейти до цих п'яти рядків, а не читати всі мільйони рядків у таблиці. Однак кластерний індекс містить лише стовпець ПК як ключовий стовпець. Після прочитання рядка в пам'яті нам потрібно застосувати фільтр COL2
. Ось, PK
є присудком для пошуку і COL2
є присудком.
Сервер SQL знаходить п'ять рядків за допомогою предиката пошуку і додатково зменшує ці п'ять рядків до одного рядка зі звичайним предикатом.
Якщо я визначаю кластерний індекс інакше:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);
І запускаючи той самий запит, я отримую різні результати:
У цьому випадку SQL Server може шукати використання обох стовпців у WHERE
пункті. Рівно один ряд зчитується з таблиці за допомогою ключових стовпців.
Ще одним прикладом розглянемо цей запит:
SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;
Індекс IX_174860_IX - це індекс покриття, оскільки містить усі стовпці, необхідні для запиту. Однак COL1
є лише ключовий стовпець. SQL Server може шукати за допомогою цього стовпця, щоб знайти 1000 рядків з відповідним COL1
значенням. Він може додатково відфільтрувати ці рядки на COL2
стовпці, щоб зменшити кінцевий результат, встановлений до 0 рядків.