Differenza tra cercare predicato e predicato


12

Sto provando a ottimizzare le prestazioni di una query che abbiamo in SQL Server 2014 Enterprise.

Ho aperto il piano di query effettivo in SQL Sentry Plan Explorer e posso vedere su un nodo che ha un predicato di ricerca e anche un predicato

Qual è la differenza tra Seek Predicate e Predicate ?

inserisci qui la descrizione dell'immagine

Nota: posso vedere che ci sono molti problemi con questo nodo (ad es. Le righe Stimate vs Actual, l'IO residuo), ma la domanda non riguarda nulla di tutto ciò.


3
Il predicato di ricerca assiste il join, filtrando solo le righe che si trovano anche nell'altra tabella (che hai redatto). Il predicato (un predicato residuo) quindi elimina le righe con lo stato specifico di 2.
Aaron Bertrand

5
Rob Farley ha dichiarato quanto segue in un commento qui :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.
Aaron Bertrand

Risposte:


18

Lanciamo un milione di righe in una tabella temporanea insieme ad alcune colonne:

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);

Qui ho un indice cluster (per impostazione predefinita) sulla PKcolonna. C'è un indice non cluster su COL1che ha una colonna chiave COL1e include COL2.

Considera la seguente query:

SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;

Qui non sto usando BETWEENperché Aaron Bertrand è in giro per questa domanda.

In che modo SQL Server Optimizer dovrebbe eseguire questa query? Bene, so che il filtro attivo PKridurrà il set di risultati a cinque righe. Il server SQL può utilizzare l'indice cluster per passare a queste cinque righe anziché leggere tutti i milioni di righe nella tabella. Tuttavia, l'indice cluster ha solo la colonna PK come colonna chiave. Dopo aver letto la riga in memoria, è necessario applicare il filtro COL2. Qui, PKè un predicato di ricerca ed COL2è un predicato.

inserisci qui la descrizione dell'immagine

Il server SQL trova cinque righe usando il predicato seek e riduce ulteriormente quelle cinque righe a una riga con il predicato normale.

Se definisco l'indice cluster in modo diverso:

CREATE TABLE #174860 (
PK INT NOT NULL, 
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);

Ed eseguo la stessa query ottengo risultati diversi:

inserisci qui la descrizione dell'immagine

In questo caso, SQL Server può cercare utilizzando entrambe le colonne nella WHEREclausola. Esattamente una riga viene letta dalla tabella usando le colonne chiave.

Per un altro esempio, considera questa query:

SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;

L'indice IX_174860_IX è un indice di copertura perché contiene tutte le colonne necessarie per la query. Tuttavia, COL1è solo una colonna chiave. SQL Server può cercare con quella colonna per trovare le 1000 righe con un COL1valore corrispondente . Può inoltre filtrare ulteriormente quelle righe sulla COL2colonna per ridurre il risultato finale impostato su 0 righe.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.