Indeks Non-Clustered - kunci dan nonkeys

8

Saya hanya ingin memastikan saya berada di jalur yang benar dengan konsep-konsep ini, sehingga umpan balik akan sangat dihargai.

Inilah teori saya dari kueri yang baru saja saya optimalkan, melalui proses coba-coba dan membaca dokumentasi MSDN.

The Query

DECLARE @pic_id int
SET pic_id = 1

SELECT ROW_NUMBER() OVER (ORDER BY pic_date desc) AS row_num, *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND (hidden = 0 OR pic_id = @pic_id)

Indeks

CREATE NONCLUSTERED INDEX [IX_tbl_pics] ON [dbo].[tbl_pics] 
(
    [map_id] ASC,
    [deleted] ASC,
    [pic_date] DESC
)
INCLUDE ( [hidden], [pic_id] )

Ada juga indeks PK di pic_id

Teori

Kolom kuncinya demikian, karena digunakan dalam klausa WHERE (tetapi tidak digunakan dalam situasi ATAU) atau dan ORDER BY.

Kolom bukan kunci (TERMASUK) seperti itu, karena mereka digunakan di WHERE, tetapi karena mereka digunakan dalam skenario ATAU mereka tidak bisa (tidak = tidak akan meningkatkan kinerja) menjadi kolom kunci.

Apakah anggapan ini benar? Jika tidak, apa yang saya lewatkan?

Terima kasih!

Darthtong
sumber

Jawaban:

8

Anda meminta pengoptimal permintaan untuk menghasilkan rencana yang dapat menjawab pertanyaan:

SELECT *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND hidden = 0;

Sisanya adalah bulu (termasuk OR pic_id = @pic_id). Ini akan menjadi pemindaian tabel, dijamin, karena selektivitas yang rendah dari predikat yang terlibat (saya yakin deleteddan hidden0/1, dan map_ipsaya ragu itu memiliki dampak signifikan). Satu-satunya predikat yang dapat menyimpan kueri adalah pic_id = @pic_idtetapi dengan menempatkannya dalam kondisi ATAU Anda membunuh peluangnya. Tidak ada indeks sekunder yang dapat membantu itu, secara realistis. Penambahan ROW_NUMBER akan mengurutkan, kemungkinan besar, tetapi kerusakan sebenarnya adalah pemindaian.

Ini adalah penyebab yang hilang. Munculkan persyaratan realistis.

Remus Rusanu
sumber
6

Apakah kunci utama juga indeks berkerumun? Jika demikian, tidak ada alasan untuk INCLUDE (pic_id)karena indeks berkerumun unik sudah akan digunakan sebagai bookmark dalam indeks nonclustered.

Sejauh apa yang Anda bicarakan dengan OR, itu adalah bagian kedua dari WHERE, tetapi Anda hanya mengandalkan selektivitas yang pertama untuk melakukan sebagian besar pekerjaan (sambil mengandalkan INCLUDE untuk menghindari pergi ke meja).

Tetapi dengan memiliki * di sana, Anda mungkin harus pergi ke meja.

Di sisi lain, saya mungkin tidak mendesain indeks saya berdasarkan satu permintaan tunggal kecuali permintaan ini sangat banyak digunakan tanpa memperhitungkan lebih banyak beban. Dan masih melihat rencana eksekusi tidak ada salahnya.

Cade Roux
sumber