Різниця між пошуком присудка і присудка


12

Я намагаюся налаштувати запит, який у нас є в SQL Server 2014 Enterprise.

Я відкрив власне план запитів у SQL Plan Explorer Explorer і на одному вузлі бачу, що він має предикат Seek, а також предикат

Яка різниця між пошуком присудка та присудка ?

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

Примітка. Я можу помітити, що з цим вузлом виникає багато проблем (наприклад, Оцінені проти фактичних рядків, залишковий IO), але питання не стосується жодної з них.


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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.