Saya dapat memahami keinginan untuk menghindari keharusan menggunakan kursor karena overhead dan ketidaknyamanan, tetapi sepertinya ada beberapa kursor-fobia-mania serius yang terjadi di mana orang akan berusaha keras untuk menghindari keharusan menggunakannya.
Misalnya, satu pertanyaan bertanya bagaimana melakukan sesuatu yang jelas sepele dengan kursor dan jawaban yang diterima diajukan menggunakan kueri rekursif ekspresi tabel umum (CTE) dengan fungsi kustom rekursif, meskipun ini membatasi jumlah baris yang dapat diproses menjadi 32 (Karena batas panggilan fungsi rekursif di sql server). Ini menurut saya sebagai solusi yang mengerikan untuk umur panjang sistem, belum lagi upaya luar biasa hanya untuk menghindari menggunakan kursor sederhana.
Apa alasan untuk tingkat kebencian gila ini? Sudahkah beberapa 'otoritas terkenal' mengeluarkan fatwa terhadap kursor? Apakah beberapa kejahatan yang tak terkatakan mengintai di jantung kursor yang merusak moral anak-anak atau sesuatu?
Pertanyaan wiki, lebih tertarik pada jawaban daripada rep.
Info Terkait:
EDIT: izinkan saya lebih tepat: Saya mengerti bahwa kursor tidak boleh digunakan sebagai pengganti operasi relasional normal ; itu adalah no-brainer. Yang tidak saya mengerti adalah orang-orang akan keluar dari jalan mereka untuk menghindari kursor seperti mereka memiliki barang rampasan atau sesuatu, bahkan ketika kursor adalah solusi yang lebih sederhana dan / atau lebih efisien. Kebencian irasional yang membuatku bingung, bukan efisiensi teknis yang jelas.
32
adalah omong kosong. Mungkin Anda berpikir untuk pemicu rekursif dan max@@NESTLEVEL
dari32
. Itu dapat diatur dalam kueriOPTION (MAXRECURSION N)
dengan default100
dan0
artinya tidak terbatas.Jawaban:
"Overhead" dengan kursor hanyalah bagian dari API. Kursor adalah cara kerja bagian RDBMS di bawah tenda. Seringkali
CREATE TABLE
danINSERT
memilikiSELECT
pernyataan, dan implementasinya adalah implementasi kursor internal yang jelas.Menggunakan "operator berbasis setel" yang lebih tinggi, menggabungkan hasil kursor ke dalam satu set hasil tunggal, yang berarti lebih sedikit API bolak-balik.
Kursor mendahului bahasa modern yang menyediakan koleksi kelas satu. Old C, COBOL, Fortran, dll., Harus memproses baris satu per satu karena tidak ada gagasan "koleksi" yang dapat digunakan secara luas. Java, C #, Python, dll., Memiliki struktur daftar kelas satu yang berisi set hasil.
Masalah Lambat
Di beberapa lingkaran, relasional bergabung adalah sebuah misteri, dan orang-orang akan menulis kursor bersarang daripada gabung sederhana. Saya telah melihat operasi berulang bersarang epik ditulis sebagai banyak dan banyak kursor. Mengalahkan optimasi RDBMS. Dan berjalan sangat lambat.
SQL rewrites sederhana untuk menggantikan loop kursor bersarang dengan gabungan dan satu, kursor datar dapat membuat program berjalan dalam waktu ke-100. [Mereka pikir saya adalah dewa optimasi. Yang saya lakukan adalah mengganti loop bersarang dengan bergabung. Masih menggunakan kursor.]
Kebingungan ini sering mengarah pada dakwaan kursor. Namun, itu bukan kursor, itu adalah penyalahgunaan kursor itulah masalahnya.
Masalah Ukuran
Untuk set hasil yang benar-benar epik (yaitu, membuang tabel ke file), kursor sangat penting. Operasi berbasis set tidak dapat mematerialisasi set hasil yang sangat besar sebagai satu kumpulan dalam memori.
Alternatif
Saya mencoba menggunakan lapisan ORM sebanyak mungkin. Tetapi itu memiliki dua tujuan. Pertama, kursor dikelola oleh komponen ORM. Kedua, SQL dipisahkan dari aplikasi menjadi file konfigurasi. Bukan karena kursornya buruk. Ini adalah pengkodean semua yang terbuka, ditutup dan diambil bukan pemrograman nilai tambah.
sumber
Kursor membuat orang terlalu menerapkan pola pikir prosedural ke lingkungan berbasis set.
Dan mereka lambat !!!
Dari SQLTeam :
sumber
Ada jawaban di atas yang mengatakan "kursor adalah cara TERLambat untuk mengakses data di dalam SQL Server ... kursor lebih dari tiga puluh kali lebih lambat daripada menetapkan alternatif berbasis."
Pernyataan ini mungkin benar dalam banyak keadaan, tetapi sebagai pernyataan selimut itu bermasalah. Sebagai contoh, saya telah memanfaatkan kursor dalam situasi di mana saya ingin melakukan operasi pembaruan atau penghapusan yang memengaruhi banyak baris tabel besar yang menerima pembacaan produksi konstan. Menjalankan prosedur tersimpan yang melakukan pembaruan ini satu demi satu berakhir lebih cepat daripada operasi berbasis set, karena operasi berbasis set bertentangan dengan operasi baca dan akhirnya menyebabkan masalah penguncian yang mengerikan (dan dapat mematikan sistem produksi sepenuhnya, dalam kasus ekstrim).
Dengan tidak adanya aktivitas database lain, operasi berbasis set secara universal lebih cepat. Dalam sistem produksi, itu tergantung.
sumber
Kursor cenderung digunakan oleh pengembang SQL awal di tempat di mana operasi berbasis set akan lebih baik. Terutama ketika orang belajar SQL setelah mempelajari bahasa pemrograman tradisional, mentalitas "iterate over this records" cenderung membuat orang menggunakan kursor secara tidak tepat.
Kebanyakan buku SQL yang serius mencakup bab yang memerintahkan penggunaan kursor; yang ditulis dengan baik memperjelas bahwa kursor memiliki tempat mereka tetapi tidak boleh digunakan untuk operasi berbasis set.
Jelas ada situasi di mana kursor adalah pilihan yang benar, atau setidaknya pilihan yang benar.
sumber
Pengoptimal sering tidak dapat menggunakan aljabar relasional untuk mengubah masalah ketika metode kursor digunakan. Seringkali kursor adalah cara yang bagus untuk menyelesaikan masalah, tetapi SQL adalah bahasa deklaratif, dan ada banyak informasi dalam database, dari kendala, hingga statistik dan indeks yang berarti bahwa pengoptimal memiliki banyak pilihan untuk menyelesaikan masalah. masalah, sedangkan kursor secara eksplisit mengarahkan solusi.
sumber
Dalam Oracle PL / SQL kursor tidak akan menghasilkan kunci tabel dan dimungkinkan untuk menggunakan pengumpulan massal / pengambilan massal.
Di Oracle 10 kursor implisit yang sering digunakan
secara implisit mengambil 100 baris sekaligus. Pengumpulan massal / pengambilan massal secara eksplisit juga dimungkinkan.
Namun PL / SQL kursor adalah sesuatu yang terakhir, gunakan ketika Anda tidak dapat memecahkan masalah dengan set-based SQL.
Alasan lain adalah paralelisasi, lebih mudah bagi database untuk memparalelkan pernyataan berbasis set besar daripada kode imperatif baris demi baris. Ini adalah alasan yang sama mengapa pemrograman fungsional menjadi lebih dan lebih populer (Haskell, F #, Lisp, C # LINQ, MapReduce ...), pemrograman fungsional membuat paralelisasi lebih mudah. Jumlah CPU per komputer meningkat sehingga paralelisasi semakin menjadi masalah.
sumber
Secara umum, karena pada basis data relasional, kinerja kode menggunakan kursor adalah urutan besarnya lebih buruk daripada operasi berbasis set.
sumber
Jawaban di atas belum cukup menekankan pentingnya mengunci. Saya bukan penggemar kursor karena mereka sering menghasilkan kunci level meja.
sumber
Untuk apa nilainya, saya telah membaca bahwa "satu" tempat kursor akan melakukan rekan set-nya berada dalam total berjalan. Di atas sebuah meja kecil, kecepatan merangkum baris di atas urutan dengan kolom lebih menyukai operasi berbasis set tetapi ketika tabel bertambah dalam ukuran baris, kursor akan menjadi lebih cepat karena hanya dapat membawa nilai total berjalan ke lintasan berikutnya dari tabel. lingkaran. Sekarang di mana Anda harus melakukan total berjalan adalah argumen yang berbeda ...
sumber
Saya setuju dengan artikel di halaman ini:
http://weblogs.sqlteam.com/jeffs/archive/2008/06/05/sql-server-cursor-removal.aspx
sumber
Di luar masalah kinerja (bukan), saya pikir kegagalan kursor terbesar adalah mereka menyakitkan untuk di-debug. Terutama dibandingkan dengan kode di sebagian besar aplikasi klien di mana debugging cenderung relatif mudah dan fitur bahasa cenderung lebih mudah. Bahkan, saya berpendapat bahwa hampir semua yang dilakukan seseorang dalam SQL dengan kursor mungkin harus terjadi di aplikasi klien.
sumber
Bisakah Anda memposting contoh kursor atau tautan ke pertanyaan? Mungkin ada cara yang lebih baik daripada CTE rekursif.
Selain komentar lain, kursor bila digunakan dengan tidak benar (yang sering) menyebabkan kunci halaman / baris yang tidak perlu.
sumber
Anda mungkin dapat menyimpulkan pertanyaan Anda setelah paragraf kedua, daripada memanggil orang-orang "gila" hanya karena mereka memiliki sudut pandang yang berbeda dari yang Anda lakukan dan jika tidak mencoba mengejek para profesional yang mungkin memiliki alasan yang sangat baik untuk merasakan cara mereka melakukannya.
Mengenai pertanyaan Anda, walaupun pasti ada situasi di mana kursor dapat dipanggil, menurut pengalaman saya pengembang memutuskan bahwa kursor "harus" digunakan JAUH lebih sering daripada yang sebenarnya terjadi. Peluang seseorang melakukan kesalahan di sisi terlalu banyak menggunakan kursor vs tidak menggunakannya ketika mereka seharusnya JAUH lebih tinggi menurut saya.
sumber
pada dasarnya 2 blok kode yang melakukan hal yang sama. mungkin itu contoh yang agak aneh tapi itu membuktikan intinya. SQL Server 2005:
pembaruan tunggal membutuhkan 156 ms sementara kursor mengambil 2016 ms.
sumber