Pertanyaannya adalah
SELECT SUM(Amount) AS SummaryTotal
FROM PDetail WITH(NOLOCK)
WHERE ClientID = @merchid
AND PostedDate BETWEEN @datebegin AND @dateend
Tabel ini berisi 103.129.000 baris.
Paket cepat dicari oleh ClientId dengan predikat residual pada tanggal tersebut tetapi perlu melakukan 96 pencarian untuk mengambil Amount
. The <ParameterList>
bagian dalam rencana adalah sebagai berikut.
<ParameterList>
<ColumnReference Column="@dateend"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@datebegin"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@merchid"
ParameterRuntimeValue="(78155)" />
</ParameterList>
Rencana lambat mencari berdasarkan tanggal dan memiliki pencarian untuk mengevaluasi predikat residual pada ClientId dan untuk mengambil jumlah (Diperkirakan 1 vs Sebenarnya 7.388.383). The <ParameterList>
Bagian ini
<ParameterList>
<ColumnReference Column="@EndDate"
ParameterCompiledValue="'2013-02-01 23:59:00.000'"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@BeginDate"
ParameterCompiledValue="'2013-01-01 00:00:00.000'"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@ClientID"
ParameterCompiledValue="(78155)"
ParameterRuntimeValue="(78155)" />
</ParameterList>
Dalam kasus kedua ParameterCompiledValue
ini tidak kosong. SQL Server berhasil mengendus nilai yang digunakan dalam kueri.
Buku "SQL Server 2005 Praktis Mengatasi Masalah" memiliki ini untuk mengatakan tentang menggunakan variabel lokal
Menggunakan variabel lokal untuk mengalahkan parameter sniffing adalah trik yang cukup umum, tetapi OPTION (RECOMPILE)
dan OPTION (OPTIMIZE FOR)
petunjuk ... umumnya solusi yang lebih elegan dan sedikit kurang berisiko
Catatan
Dalam SQL Server 2005, kompilasi tingkat pernyataan memungkinkan untuk kompilasi pernyataan individu dalam prosedur tersimpan untuk ditunda sampai sebelum pelaksanaan pertama dari permintaan. Pada saat itu nilai variabel lokal akan diketahui. Secara teoritis SQL Server dapat memanfaatkan ini untuk mengendus nilai variabel lokal dengan cara yang sama seperti mengendus parameter. Namun karena itu umum untuk menggunakan variabel lokal untuk mengalahkan sniffing parameter dalam SQL Server 7.0 dan SQL Server 2000+, mengendus variabel lokal tidak diaktifkan di SQL Server 2005. Ini mungkin diaktifkan dalam rilis SQL Server di masa depan meskipun yang baik alasan untuk menggunakan salah satu opsi lain yang diuraikan dalam bab ini jika Anda punya pilihan.
Dari tes cepat akhir ini perilaku yang dijelaskan di atas masih sama pada 2008 dan 2012 dan variabel tidak diendus untuk kompilasi ditangguhkan tetapi hanya ketika OPTION RECOMPILE
petunjuk eksplisit digunakan.
DECLARE @N INT = 0
CREATE TABLE #T ( I INT );
/*Reference to #T means this statement is subject to deferred compile*/
SELECT *
FROM master..spt_values
WHERE number = @N
AND EXISTS(SELECT COUNT(*) FROM #T)
SELECT *
FROM master..spt_values
WHERE number = @N
OPTION (RECOMPILE)
DROP TABLE #T
Meskipun kompilasi ditangguhkan, variabel tidak terendus dan estimasi jumlah baris tidak akurat
Jadi saya berasumsi bahwa rencana lambat berkaitan dengan versi kueri parameterised.
Itu ParameterCompiledValue
sama dengan ParameterRuntimeValue
untuk semua parameter jadi ini bukan sniffing parameter khas (di mana paket dikompilasi untuk satu set nilai kemudian jalankan untuk set nilai lain).
Masalahnya adalah bahwa paket yang dikompilasi untuk nilai parameter yang benar tidak pantas.
Anda kemungkinan akan mengalami masalah dengan tanggal yang disebutkan di sini dan di sini . Untuk tabel dengan 100 juta baris, Anda harus memasukkan (atau memodifikasi) 20 juta sebelum SQL Server akan secara otomatis memperbarui statistik untuk Anda. Tampaknya terakhir kali mereka diperbarui nol baris cocok dengan rentang tanggal dalam kueri tetapi sekarang 7 juta melakukannya.
Anda dapat menjadwalkan pembaruan statistik yang lebih sering, mempertimbangkan jejak bendera 2389 - 90
atau menggunakan OPTIMIZE FOR UKNOWN
sehingga hanya jatuh pada dugaan daripada dapat menggunakan statistik yang saat ini menyesatkan pada datetime
kolom.
Ini mungkin tidak diperlukan dalam versi SQL Server berikutnya (setelah 2012). Sebuah Item Connect terkait mengandung respon menarik
Diposting oleh Microsoft pada 28/8/2012 di 13.35.
Kami telah melakukan peningkatan estimasi kardinalitas untuk rilis besar berikutnya yang pada dasarnya memperbaiki ini. Menantikan untuk detail setelah preview kami keluar. Eric
Peningkatan tahun 2014 ini dilihat oleh Benjamin Nevarez menjelang akhir artikel:
Pandangan Pertama pada Penaksir Kardinalitas SQL Server Baru .
Tampaknya penduga kardinalitas baru akan mundur dan menggunakan kerapatan rata-rata dalam kasus ini daripada memberikan perkiraan 1 baris.
Beberapa detail tambahan tentang penduga kardinalitas 2014 dan masalah utama yang menanjak di sini:
Fungsionalitas baru di SQL Server 2014 - Bagian 2 - Estimasi Kardinalitas Baru