Catatan:Posting ini awalnya diterbitkan hanya di eBook kami, High Performance Techniques for SQL Server, Volume 3. Anda dapat mengetahui tentang eBook kami di sini.
Lebih dari tiga tahun yang lalu, saya menulis posting tentang opsi kursor di SQL Server, dan mengapa Anda harus mengganti default:
- Apa pengaruh opsi kursor yang berbeda?
Saya ingin memposting tindak lanjut untuk menegaskan kembali bahwa – meskipun Anda tidak boleh hanya menerima default – Anda benar-benar harus memikirkan opsi mana yang paling sesuai untuk skenario Anda. Saya juga ingin mengklarifikasi beberapa item yang muncul di komentar di postingan itu.
Andrew Kelly mengemukakan poin yang bagus, dan itu adalah STATIC
kursor membuat salinan hasil satu kali, memasukkannya ke dalam tempdb, dan kemudian menghindari masalah konkurensi yang dapat memengaruhi DYNAMIC
kursor. Satu opsi bukanlah pemenang yang jelas atas yang lain dalam semua kasus; misalnya, Anda mungkin memiliki banyak kursor (atau kursor dengan hasil yang sangat besar) dan/atau tempdb yang sudah terlalu terbebani dan tidak ingin menurunkan tekanan tambahan di sana. Tapi itu adalah sesuatu yang layak untuk diuji.
Fabiano juga mengemukakan poin bagus bahwa keduanya DYNAMIC
dan FAST_FORWARD
kursor bisa rentan terhadap masalah Hallowe'en (dibahas oleh Paul White dalam seri 4 bagian, mulai dari sini). Paul juga berkomentar bahwa FAST_FORWARD
mungkin tidak rentan terhadap masalah, tergantung pada apakah pengoptimal memilih paket statis atau dinamis (Marc Friedman dari Microsoft menjelaskannya dengan sangat rinci di sini).
Akhirnya, saya ingin menunjukkan bahwa tidak semua kursor default dibuat sama. Saya menjalankan beberapa tes dan memeriksa bagaimana SQL Server memutuskan untuk mengatur opsi kursor di bawah berbagai skenario (divalidasi menggunakan sys.dm_exec_cursors
fungsi manajemen dinamis). Kodenya cukup sederhana:
DECLARE c CURSOR FOR [...blah blah...]; SELECT properties FROM sys.dm_exec_cursors(@@SPID);
Berikut adalah hasil dari skenario yang saya uji:
Kueri kursor didasarkan pada… | Ketik | Konkurensi | Cakupan |
---|---|---|---|
konstanta (FOR SELECT 1 atau FOR SELECT SYSDATETIME() ) | Snapshot | Hanya Baca | Global |
tabel #temp / ##temp | Dinamis | Optimis | Global |
tabel / tampilan pengguna | Dinamis | Optimis | Global |
tampilan katalog / DMV | Snapshot | Hanya Baca | Global |
gabung #tmp -> tabel / tampilan pengguna | Dinamis | Optimis | Global |
gabung #tmp -> tampilan katalog / DMV | Snapshot | Hanya Baca | Global |
gabung dengan tabel / tampilan pengguna -> tampilan katalog / DMV | Snapshot | Hanya Baca | Global |
Kredit yang jatuh tempo – investigasi ini dipicu oleh jawaban dari Jeroen Mostert di Stack Overflow.
Jadi Anda harus menyadari bahwa opsi default untuk kursor Anda, jika Anda tidak menimpanya, mungkin berbeda tergantung pada kueri yang mendasari kursor. Jika Anda mengharapkan perilaku tertentu dalam setiap atau semua kasus, biasakan untuk secara eksplisit menentukan opsi yang Anda inginkan.
Tapi sungguh, intinya adalah…
…berhenti menggunakan kursor. Benar-benar ada sedikit masalah hari ini di mana solusi terbaik adalah kursor, terutama jika Anda menggunakan SQL Server 2012 atau lebih baik - di mana hampir setiap masalah yang secara tradisional diselesaikan oleh kursor dapat diselesaikan menggunakan peningkatan fungsi jendela. Jika Anda masih merasa perlu menggunakan kursor, silakan ikuti saran di postingan ini dan pendahulunya untuk menentukan opsi mana yang harus Anda gunakan.