Saya memiliki pernyataan penghapusan yang menggunakan paket yang buruk saat dijalankan di dalam prosedur tersimpan, tetapi memilih paket yang lebih baik ketika dijalankan secara ad-hoc.
Saya telah membangun kembali semua indeks untuk tabel yang digunakan oleh kueri dan menjatuhkan semua cache. Pengoptimal masih memilih rencana yang salah untuk prosedur tersimpan.
Saya ingin tahu mengapa pengoptimal menggunakan rencana eksekusi yang berbeda untuk prosedur tersimpan versus ad-hoc SQL.
UPDATE: Saya kira itu pasti parameter setelah semua- ketika saya menjalankan kode ad-hoc dengan variabel hardcoded, saya bisa mendapatkan paket "buruk" dengan nilai yang benar (ini adalah tanggal, nilai yang berumur satu tahun tampaknya menghasilkan rencana "baik"). Sekarang untuk mencoba memaksa rencana "baik" pada proc dengan menggunakan petunjuk kueri.
SOLUSI: Saya akhirnya mendapatkan rencana yang saya inginkan dengan menggunakan petunjuk MENGOPTIMALKAN UNTUK TIDAK DIKENAL.
sumber
WHERE
klausa?Jawaban:
Tersangka biasa:
Butir 1: pengoptimal dapat memilih rencana terbaik untuk konstanta.
Ubah konstanta = ubah rencana. Plen parametrised dapat direset
Poin 2 akan memperkenalkan konversi implisit karena prioritas datatype
misalnya kolom varchar dibandingkan dengan parameter nvarchar
Butir 3: gunakan parameter masking atau OPTIMASI UNTUK TIDAK DIKETAHUI
Edit: Untuk menguji: jalankan proc tersimpan, jalankan sp_updatestats, jalankan lagi. Ini akan membatalkan paket cache yang lebih baik daripada menghapus cache paket
Sunting: setelah komentar jcolebrand
Anda dapat menonaktifkan beberapa cara. 3 utama adalah
Parameter masking:
Masking dan petunjuk OPTIMIZE memiliki efek yang sama (mungkin karena alasan yang berbeda). Artinya, pengoptimal harus menggunakan statistik dan distribusi data ( Catatan: masih dalam pengujian oleh Mark Storey-Smith )
mengevaluasi parameter pada kemampuan mereka sendiri ?, daripada apa panggilan terakhir mereka. Pengoptimal dapat mengkompilasi ulang atau tidak. SQL Server 2005 menambahkan kompilasi tingkat pernyataan sehingga dampaknya lebih kecilSekarang, mengapa rencana dengan parameter "mengendus" adalah "lengket" dibandingkan dengan parameter bertopeng / "tidak diketahui", saya tidak yakin.
Saya telah menggunakan parameter masking sejak SQL Server 2000 untuk semua kecuali kode paling sederhana. Saya telah mencatat bahwa itu mungkin terjadi dengan kode yang lebih kompleks. Dan di pekerjaan lama saya, saya memiliki beberapa procs laporan bahwa saya dapat mengubah default parameter paket. Saya rasa pendekatan "pemujaan kargo" lebih mudah daripada panggilan dukungan.
Edit 2, 12 Okt 2011, setelah mengobrol
Parameter masking dan MENGOPTIMALKAN UNTUK TIDAK DIKETAHUI memiliki efek yang sama sejauh yang saya tahu
. Petunjuknya lebih bersih daripada masking tetapi ditambahkan dengan SQL Server 2008.
Parameter sniffing terjadi pada waktu kompilasi.
DENGAN RECOMPILE menghasilkan rencana baru setiap eksekusi. Ini berarti pilihan standar yang buruk akan memengaruhi rencana. Di pekerjaan terakhir saya, saya bisa mendemonstrasikan ini dengan mudah dengan beberapa kode laporan: mengubah standar parameter mengubah paket tanpa memperhatikan parameter yang disediakan.
Artikel MS Connect ini menarik: Penggunaan indeks suboptimal dalam prosedur tersimpan (disebutkan dalam salah satu jawaban SO di bawah)
Masalah luar biasa
Apakah sniffing masih berlaku dengan WITH RECOMPILE? Yaitu, jika pengoptimal tahu untuk membuang rencana apakah itu bertujuan untuk digunakan kembali?
Mengapa rencana mengendus "lengket"?
Tautan dari SO:
https://stackoverflow.com/q/272726/27535
Remus Rusanu (tim MS SQL) dan saya mengalami bunfight di sini pada SO
sumber
OPTION (RECOMPILE)
atau seluruh procWITH RECOMPILE
untuk memaksa SQL Server untuk mengabaikan rencana yang ada.OPTIMIZE
, karena Microsoft adalah perusahaan Amerika. :)Jangan lupa bahwa pengaturan ANSI yang telah Anda atur untuk rencana koneksi berperan dalam pemilihan paket eksekusi. Saat aplikasi memanggil prosedur tersimpan, mungkin pengaturan ANSI berbeda dari koneksi SSMS Anda.
sumber