Perbedaan antara Mencari Predikat dan Predikat

12

Saya mencoba untuk menyelaraskan kueri yang kami miliki di SQL Server 2014 Enterprise.

Saya telah membuka rencana kueri yang sebenarnya di SQL Sentry Plan Explorer dan saya dapat melihat pada satu simpul bahwa ia memiliki Predikat Mencari dan juga Predikat

Apa perbedaan antara Mencari Predikat dan Predikat ?

masukkan deskripsi gambar di sini

Catatan: Saya dapat melihat bahwa ada banyak masalah dengan simpul ini (misalnya baris Estimated vs Actual, IO residual), tetapi pertanyaannya tidak terkait dengan semua itu.

Greg
sumber
3
Predikat seek assist dengan join, memfilter hanya ke baris yang juga ditemukan di tabel lain (yang telah Anda hapus). Predikat (predikat residual) kemudian menghilangkan baris dengan status spesifik 2.
Aaron Bertrand
5
Rob Farley menyatakan hal berikut dalam komentar di sini :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

Jawaban:

18

Mari kita lemparkan satu juta baris ke tabel temp bersama dengan beberapa kolom:

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

Di sini saya memiliki indeks berkerumun (secara default) pada PKkolom. Ada indeks nonclustered pada COL1yang memiliki kolom kunci COL1dan sertakan COL2.

Pertimbangkan pertanyaan berikut:

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

Di sini saya tidak menggunakan BETWEENkarena Aaron Bertrand berkeliaran di pertanyaan ini.

Bagaimana seharusnya pengoptimal SQL Server SQL permintaan? Yah, saya tahu bahwa filter aktif PKakan mengurangi hasil yang ditetapkan ke lima baris. SQL server dapat menggunakan indeks berkerumun untuk melompat ke lima baris alih-alih membaca semua juta baris dalam tabel. Namun, indeks berkerumun hanya memiliki kolom PK sebagai kolom kunci. Setelah baris dibaca ke dalam memori, kita perlu menerapkan filter COL2. Di sini, PKpredikat mencari dan COL2predikat.

masukkan deskripsi gambar di sini

SQL server menemukan lima baris menggunakan predikat seek dan selanjutnya mengurangi lima baris tersebut menjadi satu baris dengan predikat normal.

Jika saya mendefinisikan indeks klaster berbeda:

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

Dan jalankan kueri yang sama saya mendapatkan hasil yang berbeda:

masukkan deskripsi gambar di sini

Dalam hal ini, SQL Server dapat mencari menggunakan kedua kolom dalam WHEREklausa. Tepat satu baris dibaca dari tabel menggunakan kolom kunci.

Untuk satu contoh lagi pertimbangkan pertanyaan ini:

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

Indeks IX_174860_IX adalah indeks penutup karena berisi semua kolom yang diperlukan untuk kueri. Namun, hanya COL1kolom kunci. SQL Server dapat mencari dengan kolom itu untuk menemukan 1000 baris dengan COL1nilai yang cocok . Lebih lanjut dapat menyaring baris-baris pada COL2kolom untuk mengurangi hasil akhir yang ditetapkan ke 0 baris.

masukkan deskripsi gambar di sini

Joe Obbish
sumber