Saya memiliki dua pertanyaan serupa yang menghasilkan rencana kueri yang sama, kecuali bahwa satu rencana kueri menjalankan Pemindaian Indeks Cluster 1316 kali, sedangkan yang lainnya mengeksekusi 1 kali.
Satu-satunya perbedaan antara dua kueri adalah kriteria tanggal yang berbeda. Permintaan yang berjalan lama sebenarnya kriteria tanggal yang lebih sempit, dan menarik lebih sedikit data.
Saya telah mengidentifikasi beberapa indeks yang akan membantu dengan kedua permintaan, tetapi saya hanya ingin memahami mengapa operator Clustered Index Scan mengeksekusi 1316 kali pada kueri yang hampir sama dengan yang di mana ia mengeksekusi 1 kali.
Saya memeriksa statistik pada PK yang sedang dipindai, dan mereka relatif terbaru.
Permintaan asli:
select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
select incident_id as exported_incident_id
from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000'
and exported_incidents.exported_incident_id is not null
Buat rencana ini:
Setelah mempersempit kriteria rentang tanggal:
select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
select incident_id as exported_incident_id
from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
and exported_incidents.exported_incident_id is not null
Buat rencana ini:
sumber
FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
kriteria dan sejak itu telah ada jumlah sisipan yang tidak proporsional dalam kisaran itu. Diperkirakan hanya 1,07 eksekusi akan diperlukan untuk rentang tanggal tersebut. Bukan 1.316 yang terjadi dalam kenyataannya.Jawaban:
GABUNGAN setelah pemindaian memberikan petunjuk: dengan lebih sedikit baris di satu sisi penggabungan terakhir (tentu saja membaca kanan ke kiri) pengoptimal memilih "lingkaran bersarang" bukan "gabung hash".
Namun, sebelum melihat ini, saya bertujuan untuk menghilangkan Pencarian Kunci dan DISTINCT.
Pencarian kunci: indeks Anda pada FIR_Incident harus mencakup, mungkin
(FI_IncidentDate, incidentid)
atau sebaliknya. Atau miliki keduanya dan lihat mana yang lebih sering digunakan (keduanya mungkin)Ini
DISTINCT
adalah konsekuensi dariLEFT JOIN ... IS NOT NULL
. Pengoptimal telah menghapusnya (rencananya telah "meninggalkan setengah bergabung" pada JOIN akhir) tapi saya akan menggunakan EXIS untuk kejelasanSesuatu seperti:
Anda juga dapat menggunakan panduan paket dan BERGABUNG dengan petunjuk untuk membuat SQL Server menggunakan hash bergabung, tetapi cobalah untuk membuatnya bekerja lebih dulu: panduan atau petunjuk mungkin tidak akan bertahan dalam ujian waktu karena hanya berguna untuk data dan kueri yang Anda jalankan sekarang, bukan di masa mendatang
sumber