Saya mencoba memahami masalah yang kami alami dengan SQL Server 2000. Kami adalah situs web yang cukup transaksional dan kami memiliki proc tersimpan sp_GetCurrentTransactions
yang menerima customerID, dan dua tanggal.
Sekarang tergantung pada tanggal, dan pelanggan, permintaan ini dapat mengembalikan apa pun dari nol hingga 1000-an baris.
Masalahnya: apa yang kami alami adalah bahwa tiba-tiba kami akan mendapatkan sejumlah kesalahan (biasanya Execution Timeout Expired
atau serupa) untuk klien tertentu ketika mereka mencoba menjalankan proc yang disimpan. Jadi kami memeriksa kueri, menjalankannya dalam SSMS dan dan menemukan bahwa dibutuhkan 30-an. Jadi kami mengkompilasi ulang proc yang tersimpan dan -bang- sekarang berjalan dalam 300ms.
Saya sudah bicara dengan DBA kami tentang ini. Dia telah memberi tahu saya bahwa database membuat rencana kueri ketika kami membuat proc yang disimpan. Dia mengatakan bahwa itu adalah rencana yang bagus untuk set parameter itu, tetapi jika Anda melempar set parameter tertentu padanya, maka rencana itu tidak akan menjadi rencana terbaik untuk data itu, sehingga Anda akan melihatnya berjalan lambat.
Opsi yang disajikan kepada saya adalah langkah yang kueri masalah dari proc yang disimpan dan kembali ke SQL dinamis yang memiliki rencana eksekusi yang dibuat pada setiap proses.
Ini terasa seperti langkah mundur bagi saya dan saya merasa harus ada jalan keluar untuk hal ini. Apakah ada cara lain untuk mengatasi masalah ini?
Setiap dan semua tanggapan dihargai.
sumber
Jawaban:
Masalah ini disebut sniffing parameter.
Versi SQL Server yang lebih baru memberi Anda lebih banyak opsi untuk mengatasinya seperti
OPTION (RECOMPILE)
atauOPTIMIZE FOR
petunjuk.Anda dapat mencoba mendeklarasikan variabel dalam prosedur tersimpan, menetapkan nilai parameter ke variabel dan menggunakan variabel di tempat parameter karena kedengarannya seolah-olah sebagian besar waktu Anda mendapatkan paket yang cukup memuaskan.
Biasanya rencana yang paling buruk adalah dikompilasi untuk parameter dengan selektivitas sangat tinggi tetapi dijalankan dengan parameter dengan selektivitas rendah.
Dengan asumsi rencana yang dihasilkan lebih kuat dengan pendekatan ini dan memuaskan untuk semua nilai parameter maka keuntungan dari pendekatan ini dibandingkan yang disarankan oleh JNK adalah bahwa hal itu tidak menimbulkan biaya kompilasi untuk setiap panggilan.
Kerugiannya adalah bahwa untuk beberapa eksekusi, waktu berjalan mungkin lebih besar daripada untuk sebuah rencana yang dirancang khusus untuk nilai parameter tersebut sehingga merupakan trade off dari waktu kompilasi vs waktu eksekusi.
sumber
Alih-alih menggunakan SQL dinamis, Anda selalu bisa mengubah panggilan proc ke:
EXEC Database.dbo.usp_Myprocedure 'Parameter' WITH RECOMPILE
The
WITH RECOMPILE
kekuatan (Anda dapat menebaknya!) Mengkompilasi ulang rencana eksekusi setiap kali dijalankan.Anda juga dapat memasukkan
WITH RECOMPILE
dalam definisi proc yang disimpan:sumber
Anda juga dapat mencoba memutuskan untuk basis data yang akan digunakan, meskipun Anda akan sedikit berkelahi dengan pengoptimal, sehingga lebih rapuh daripada yang Anda harapkan.
Tekniknya adalah ini - pecahkan prosedur yang tersimpan menjadi 2, satu dimaksudkan untuk satu set parameter, satu untuk yang lain. Tambahkan klausa mana ke masing-masing sehingga di antara mereka mereka mencakup semua kasus yang mungkin. Lihatlah paket kueri - satu harus dioptimalkan untuk satu set parameter, yang lain untuk set lainnya. Anda mungkin harus mengutak-atik kueri agar hal ini terjadi, atau ini mungkin tidak mungkin dicapai untuk kueri Anda, dalam hal ini pendekatan ini tidak akan berfungsi.
Sekarang buat prosedur tersimpan asli Anda periksa nilai parameter dan kirim ke salah satu dari dua prosedur yang tersimpan dari paragraf sebelumnya.
Ini bisa berhasil, tapi ini semacam peretasan untuk memaksa pengoptimal bekerja lebih efektif untuk kueri Anda. Seperti semua peretasan seperti itu, dalam versi basis data yang akan datang mungkin tidak perlu atau bahkan memperburuk keadaan. Jadi, bahkan jika itu berhasil, Anda harus memutuskan apakah itu layak.
sumber
Anda juga dapat mencoba
SET FORCEPLAN
dan mengindeks petunjuk.http://msdn.microsoft.com/en-us/library/ms188344.aspx
Ini pada dasarnya memungkinkan Anda untuk memilih urutan pesanan yang terjadi.
Anda dapat memiliki petunjuk indeks untuk memastikan bahwa server SQL menggunakan indeks yang benar.
sumber
Hmmm ... jika kita fokus hanya pada prosedur tersimpan yang satu ini, saya akan terkejut bahwa menggunakan rencana eksekusi yang di-cache akan menyebabkan masalah yang Anda lihat. Saya akan meminta untuk melihat rencana pelaksanaan prosedur tersimpan menggunakan seperangkat parameter untuk pelanggan dan dua tanggal. Saya ingin tahu apakah indeks yang lebih spesifik akan membantu -> seperti pada customerId, dan hanya dua tanggal?
sumber
Tiba-tiba menurunkan kinerja terdengar seperti rencana kueri yang tidak efisien yang dihasilkan, mungkin karena statistik yang hilang. Jalankan profiler SQL Server dengan kategori acara "Kesalahan dan Peringatan" yang ditetapkan dan lihat apakah ada peringatan tentang statistik yang hilang.
Anda mungkin juga kehilangan indeks, atau Anda mungkin perlu men-defrag indeks karena mereka mungkin terlalu terfragmentasi untuk SQL Server untuk digunakan, sehingga berpikir bahwa Pemindaian Tabel akan menghasilkan lebih sedikit I / O.
@JNK memunculkan poin yang bagus tentang procs yang disimpan - ini dikompilasi dimuka dan rencana kueri akan disimpan bersama dengan prosedur yang tersimpan.
Saya tidak serta merta setuju dengan penggunaan DENGAN RECOMPILE karena Anda kemudian kehilangan manfaat dari rencana kueri yang disimpan dan digunakan kembali. Ada beberapa kasus saat ini diperlukan - yaitu jika statistik distribusi Anda di tabel yang mendasari sangat berbeda antara panggilan, tetapi secara umum, setelah data dalam tabel matang, distribusi data di dalam tabel akan bervariasi minimal.
Jadi, untuk meringkas:
sumber