Разница между поиском предиката и предиката

12

Я пытаюсь настроить производительность запроса, который есть у нас в SQL Server 2014 Enterprise.

Я открыл фактический план запроса в SQL Sentry Plan Explorer, и я вижу на одном узле, что у него есть Предикат поиска, а также Предикат

В чем разница между поиском предиката и предиката ?

введите описание изображения здесь

Примечание: я вижу, что есть много проблем с этим узлом (например, Оцененные против Фактических строк, остаточный ввод-вывод), но вопрос не касается ни одного из этого.

Greg
источник
3
Предикат поиска помогает с объединением, фильтруя только те строки, которые также находятся в другой таблице (которую вы отредактировали). Предикат (остаточный предикат) затем удаляет строки с определенным статусом 2.
Аарон Бертран
5
Роб Фарли заявил следующее в комментарии здесь :The Seek Predicate can be used to find the start of the RangeScan and then when to stop, while the Predicate is the "check" that is applied to every row in the Range.
Аарон Бертран

Ответы:

18

Давайте бросим один миллион строк во временную таблицу вместе с несколькими столбцами:

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 может использовать кластерный индекс для перехода к этим пяти строкам вместо чтения всех миллионов строк в таблице. Однако кластерный индекс имеет только столбец PK в качестве ключевого столбца. Как только строка будет считана в память, нам нужно применить фильтр 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 строк.

введите описание изображения здесь

Джо Оббиш
источник