(Pertanyaan pindah dari SO)
Saya punya tabel (data dummy) dengan indeks berkelompok berisi 2 kolom:
Sekarang saya menjalankan dua pertanyaan itu:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
Rencana eksekusi aktual untuk kedua kueri adalah:
Seperti yang Anda lihat, yang pertama menggunakan SCAN sedangkan yang kedua menggunakan SEEK.
Namun - menambahkan OPTION (RECOMPILE)permintaan pertama, membuat rencana eksekusi juga menggunakan SEEK:
Teman-teman di obrolan DBA memberi tahu saya bahwa:
Dalam permintaan Anda, @ productid = 1, yang berarti bahwa (productID = @ productID ATAU @productID IS NULL) dapat disederhanakan menjadi (productID = @ productID). Yang pertama membutuhkan pemindaian untuk bekerja dengan nilai @productID, yang terakhir bisa menggunakan pencarian. Jadi, ketika Anda menggunakan RECOMPILE, SQL Server akan melihat nilai apa yang sebenarnya Anda miliki di @productID dan membuat rencana terbaik untuk itu. Dengan nilai non-null di @productID, pencarian adalah yang terbaik. Jika nilai @productID tidak diketahui, paket harus sesuai dengan nilai yang memungkinkan di @productID, yang akan membutuhkan pemindaian. Diperingatkan: OPSI (RECOMPILE) akan memaksa kompilasi ulang rencana setiap kali Anda menjalankannya, yang akan menambahkan beberapa milidetik untuk setiap eksekusi. Padahal ini hanya masalah jika kueri berjalan sangat sering.
Juga:
Jika @productID adalah null, untuk nilai apa yang Anda cari? Jawab: tidak ada yang bisa dicari. Semua nilai memenuhi syarat.
Saya mengerti bahwa OPTION (RECOMPILE)memaksa SQL Server untuk melihat apa nilai aktual dari parameter, dan melihat apakah itu bisa MENCARI dengan itu.
Tapi sekarang saya kehilangan manfaat dari kompilasi di depan.
Pertanyaan
IMHO - SCAN hanya akan terjadi jika param adalah null.
Tidak apa-apa - biarkan SQL SERVER membuat rencana eksekusi untuk SCAN.
TETAPI jika SQL Server melihat bahwa saya menjalankan kueri ini berkali-kali dengan nilai:, 1,1lalu mengapa ia tidak membuat rencana eksekusi LAIN dan menggunakan MENCARI untuk itu?
AFAIK - SQL membuat rencana eksekusi untuk kueri yang paling banyak ditemui .
Mengapa SQL SERVER tidak menyimpan rencana eksekusi untuk:
@productid int =1 , @priceid int = 1
(Saya menjalankannya berkali-kali dengan nilai-nilai itu)
- Apakah mungkin untuk memaksa SQL untuk menjaga rencana eksekusi itu (yang menggunakan SEEK) - untuk permohonan di masa mendatang?


