Tabel Retailer_Relations memiliki indeks PK komposit berikut dan indeks yang disarankan
Meskipun indeks yang hilang dapat membantu dan pasti dapat bekerja, saya tidak akan menghabiskan terlalu banyak waktu untuk indeks yang hilang, petunjuk ini dibuat pada perkiraan rencana eksekusi, bukan pada rencana eksekusi yang sebenarnya.
Lebih tepatnya, petunjuk indeks ini didasarkan pada premis untuk mengurangi biaya Query Bucks ™ yang digunakan oleh operator dalam paket tersebut. Pengoptimal menghitung perkiraan biaya, dan menambahkan petunjuk indeks yang hilang sesuai.
Akibatnya mereka bisa sangat salah. Jika Anda tidak yakin apakah itu akan membantu, hal terbaik untuk dilakukan adalah menguji situasi sebelum dan sesudah. Anda bisa melakukan ini dengan menambahkan pernyataan
SET STATISTICS IO, TIME ON;
sebelum menjalankan kueri.
Anda juga dapat menggunakan statistikparser untuk mempermudah membaca statistik ini.
Mungkinkah ini karena urutan kolom dalam indeks?
Itu benar, membuat indeks yang hilang dapat meningkatkan selektivitas pada kueri, misalnya jika kueri Anda terlihat seperti ini:
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
atau seperti ini:
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
Alasan di balik ini adalah bahwa kedua indeks dapat mencari di RetailerID, bagian itu tidak akan berubah. Tetapi bagaimana jika filter / pemesanan tambahan diterapkan pada RelationType? Itu akan menjadi semua tempat di indeks berkerumun, sebagai akibat dari itu menjadi nilai kunci ketiga, bukan nilai kunci kedua. Dan seperti yang kita tahu, itu adalah nilai kunci kedua di NCI.
Oke, tetapi kapan atau bagaimana indeks nonclustered meningkatkan kueri?
Beberapa kasus bisa:
- Jika relationType memfilter banyak nilai, sisa I / O bisa tinggi, sehingga menghasilkan kebutuhan indeks yang tidak tercakup (Pertanyaan # 1)
- Pemesanan pada dua kolom terjadi (Satu arah), dan resultset besar (Query # 2).
- Seperti yang disebutkan @AaronBertrand: jika perbedaan ukuran CI dibandingkan dengan NCI adalah jumlah yang cukup besar, menambahkan NCI akan mengurangi halaman yang dibaca oleh pertanyaan yang mendapat manfaat darinya.
Catatan NCI
Sebagai catatan tambahan, menambahkan kolom kunci ke daftar sertakan dalam NCI Anda tidak benar-benar diperlukan, karena kolom kunci CI secara otomatis termasuk dalam semua indeks Non-clustered.
Anda dapat memilih untuk melakukannya jika Anda tidak yakin apakah indeks berkerumun akan tetap sama, dan ingin kolom selalu disertakan.
Mengenai kueri itu sendiri, jika Anda menambahkan rencana eksekusi melalui PasteThePlan, kami dapat memberikan beberapa informasi lebih lanjut tentang pengindeksan / peningkatan kueri.
Pengujian
Buat tabel dan tambahkan beberapa baris
CREATE TABLE Retailer_Relations (
RetailerID int ,
RelatedRetailerID int ,
RelationType smallint,
CreatedOn datetime,
CONSTRAINT PK_Retailer_Relations
PRIMARY KEY CLUSTERED (
RetailerID ASC,
RelatedRetailerID ASC,
RelationType ASC
) ON [PRIMARY])
DECLARE @I Int = 1
WHILE @I < 1000
BEGIN
INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
VALUES(@I,@I,@I,GETDATE()
)
set @I += 1
END
Pertanyaan # 1
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
Rencanakan tanpa indeks Di Sini
Sementara itu melakukan pencarian, itu melakukan pencarian di RetailerID. Setelah itu mengeluarkan predikat I / O residual pada RelationType
Tambahkan indeks
CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
RetailerID,
RelationType
)
INCLUDE (
RelatedRetailerID
)
Predikat residual hilang, semuanya terjadi dalam predikat pencarian, di kedua kolom.
Rencana eksekusi
Dengan kueri kedua, indeks tambah bermanfaat menjadi lebih jelas:
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
Paket tanpa indeks, dengan operator Sortir:
Paket dengan indeks, menggunakan indeks menghapus operator sortir