Terinspirasi oleh pertanyaan ini di mana terdapat perbedaan pandangan tentang SET NOCOUNT ...
Haruskah kita menggunakan SET NOCOUNT ON untuk SQL Server? Jika tidak, mengapa tidak?
Apa yang dilakukannya Edit 6, pada 22 Jul 2011
Itu menekan pesan "xx baris yang terpengaruh" setelah DML apa pun. Ini adalah resultset dan ketika dikirim, klien harus memprosesnya. Ini kecil, tetapi dapat diukur (lihat jawaban di bawah)
Untuk pemicu dll, klien akan menerima beberapa "xx baris yang terpengaruh" dan ini menyebabkan semua jenis kesalahan untuk beberapa ORM, MS Access, JPA dll (lihat suntingan di bawah)
Latar Belakang:
Praktik terbaik yang diterima umum (saya pikir sampai pertanyaan ini) adalah untuk digunakan SET NOCOUNT ON
dalam pemicu dan prosedur tersimpan dalam SQL Server. Kami menggunakannya di mana-mana dan google cepat menunjukkan banyak MVP SQL Server yang menyetujui juga.
MSDN mengatakan ini dapat merusak .net SQLDataAdapter .
Sekarang, ini berarti bagi saya bahwa SQLDataAdapter terbatas hanya untuk pemrosesan CRUD karena mengharapkan pesan "n rows terpengaruh" agar cocok. Jadi, saya tidak bisa menggunakan:
- JIKA ADA untuk menghindari duplikat (tidak ada baris yang terpengaruh pesan) Catatan: gunakan dengan hati-hati
- DIMANA TIDAK ADA (lebih sedikit baris dari yang diharapkan
- Saring pembaruan sepele (mis. Tidak ada data yang benar-benar berubah)
- Lakukan akses tabel apa pun sebelumnya (seperti logging)
- Sembunyikan kompleksitas atau denormalisasi
- dll
Dalam pertanyaan, marc_s (siapa yang tahu hal-hal SQL-nya) mengatakan jangan menggunakannya. Ini berbeda dengan apa yang saya pikirkan (dan saya menganggap diri saya agak kompeten di SQL juga).
Mungkin saja saya kehilangan sesuatu (merasa bebas untuk menunjukkan yang sudah jelas), tetapi apa yang kalian pikirkan di luar sana?
Catatan: sudah bertahun-tahun sejak saya melihat kesalahan ini karena saya tidak menggunakan SQLDataAdapter saat ini.
Suntingan setelah komentar dan pertanyaan:
Edit: Lebih banyak pemikiran ...
Kami memiliki banyak klien: satu dapat menggunakan C # SQLDataAdaptor, yang lain dapat menggunakan nHibernate dari Java. Ini dapat dipengaruhi dengan berbagai cara dengan SET NOCOUNT ON
.
Jika Anda menganggap procs yang disimpan sebagai metode, maka itu bentuk yang buruk (anti-pola) untuk menganggap beberapa proses internal bekerja dengan cara tertentu untuk tujuan Anda sendiri.
Sunting 2: pemicu yang memecahkan pertanyaan nHibernate , di mana SET NOCOUNT ON
tidak dapat diatur
(dan tidak, ini bukan duplikat dari ini )
Sunting 3: Namun lebih banyak info, terima kasih kepada kolega MVP saya
- KB 240882 , masalah yang menyebabkan terputusnya SQL 2000 dan sebelumnya
- Demo perolehan kinerja
Sunting 4: 13 Mei 2011
Istirahat Linq 2 SQL juga ketika tidak ditentukan?
Sunting 5: 14 Juni 2011
Mematahkan JPA, proc yang disimpan dengan variabel tabel: Apakah JPA 2.0 mendukung variabel tabel SQL Server?
Sunting 6: 15 Agustus 2011
Kisi data "Edit rows" SSMS memerlukan SET NOCOUNT ON: Perbarui trigger dengan GROUP BY
Sunting 7: 07 Mar 2013
Lebih detail dari @RemusRusanu:
Apakah SET NOCOUNT ON benar-benar membuat banyak perbedaan kinerja
Jawaban:
Ok sekarang saya sudah melakukan penelitian, ini kesepakatannya:
Dalam protokol TDS,
SET NOCOUNT ON
hanya menyimpan 9-byte per kueri sementara teks "SET NOCOUNT ON" itu sendiri adalah 14 byte kekalahan. Dulu saya berpikir bahwa123 row(s) affected
itu dikembalikan dari server dalam teks biasa dalam paket jaringan yang terpisah tetapi itu tidak terjadi. Sebenarnya struktur kecil yang disebutDONE_IN_PROC
tertanam dalam respons. Ini bukan paket jaringan yang terpisah sehingga tidak ada perjalanan pulang-pergi yang sia-sia.Saya pikir Anda dapat tetap berpegang pada perilaku penghitungan default hampir selalu tanpa khawatir tentang kinerja. Namun ada beberapa kasus, di mana menghitung jumlah baris sebelumnya akan berdampak pada kinerja, seperti kursor hanya maju. Dalam hal ini, NOCOUNT mungkin suatu keharusan. Selain itu, sama sekali tidak perlu mengikuti moto "gunakan NOCOUNT sedapat mungkin".
Berikut adalah analisis yang sangat terperinci tentang
SET NOCOUNT
pengaturan yang tidak penting : http://daleburnett.com/2014/01/everything-ever-wanted-know-set-nocount/sumber
DONINPROC
(RPC) atauDONE
(BATCH) pesan dialirkan denganrowcount
diatur ke baris yang terpengaruh, sementaradone_count
benderatrue
, terlepas jikaNO_COUNT
adaON
. Bergantung pada implementasi lib klien dalam kasus ketika kueri memegang pernyataan SELECT atau panggilan RPC yang memilih, mungkin mengharuskan untuk menonaktifkan penghitungan ... KETIKA dinonaktifkan, baris masih dihitung untuk pernyataan pilih, tetapi flagDONE_COUNT
diatur kefalse
. Selalu baca apa yang disarankan klien Anda karena itu akan mengartikan token (message) stream bukan AndaButuh banyak penggalian untuk menemukan angka patokan nyata di sekitar NOCOUNT, jadi saya pikir saya akan membagikan ringkasan singkat.
sumber
SET NOCOUNT OFF;
dan itulah sebabnya mereka berpikir mereka tidak mendapatkan byte tambahan sebagai tanggapan. Tolok ukur yang akurat akan digunakanSET NOCOUNT ON
diSET NOCOUNT OFF
prosedur tersimpan kiri dan kanan. Dengan cara ini Anda akan mendapatkan paket TDSDONEINPROC (SET NOCOUNT ...)
, sepuluh lagiDONEINPROC (INSERT statement)
, dan kemudianRETURNVALUE(@@ROWCOUNT)
, laluRETURNSTATUS 0
untuk sp dan akhirnyaDONPROC
. Kesalahan ada karena sp kedua tidak memiliki SET NOCOUNT MATI di tubuh!Ketika SET NOCOUNT AKTIF, hitungan (menunjukkan jumlah baris yang dipengaruhi oleh pernyataan Transact-SQL) tidak dikembalikan. Saat SET NOCOUNT MATI, hitungan dikembalikan. Ini digunakan dengan pernyataan SELECT, INSERT, UPDATE, DELETE.
Pengaturan SET NOCOUNT diatur pada saat dijalankan atau dijalankan dan tidak pada waktu parse.
SET NOCOUNT ON meningkatkan kinerja prosedur tersimpan (SP).
Sintaks: SET NOCOUNT {ON | MATI }
Contoh SET NOCOUNT ON:
Contoh SET NOCOUNT MATI:
sumber
Saya kira sampai tingkat tertentu itu adalah masalah DBA vs pengembang.
Sebagai seorang pengembang, saya katakan jangan menggunakannya kecuali Anda benar-benar harus - karena menggunakannya dapat merusak kode ADO.NET Anda (seperti yang didokumentasikan oleh Microsoft).
Dan saya kira sebagai DBA, Anda akan lebih di sisi lain - menggunakannya kapan pun memungkinkan kecuali Anda benar-benar harus mencegah penggunaannya.
Juga, jika devs Anda pernah menggunakan "RecordsAffected" yang dikembalikan oleh
ExecuteNonQuery
pemanggilan metode ADO.NET , Anda dalam masalah jika semua orang menggunakanSET NOCOUNT ON
karena dalam kasus ini, ExecuteNonQuery akan selalu mengembalikan 0.Juga lihat posting blog Peter Bromberg dan periksa posisinya.
Jadi itu benar-benar bermuara pada siapa yang harus menetapkan standar :-)
Marc
sumber
Jika Anda mengatakan Anda mungkin memiliki klien yang berbeda juga, ada masalah dengan ADO klasik jika SET NOCOUNT tidak diset ON.
Satu yang saya alami secara teratur: jika prosedur tersimpan mengeksekusi sejumlah pernyataan (dan dengan demikian sejumlah pesan "baris xxx terpengaruh" dikembalikan), ADO tampaknya tidak menangani ini dan melempar kesalahan "Tidak dapat mengubah properti ActiveConnection dari objek Recordset. yang memiliki objek Command sebagai sumbernya. "
Jadi saya biasanya menganjurkan pengaturan ON kecuali ada alasan yang sangat bagus untuk tidak melakukannya. Anda mungkin telah menemukan alasan yang sangat bagus yang perlu saya baca dan baca lebih lanjut.
sumber
Dengan risiko membuat segalanya lebih rumit, saya mendorong aturan yang sedikit berbeda dengan semua yang saya lihat di atas:
NOCOUNT ON
di bagian atas proc, sebelum Anda melakukan pekerjaan apa pun di proc, tetapi juga selaluSET NOCOUNT OFF
lagi, sebelum mengembalikan semua recordset dari proc yang disimpan.Jadi "umumnya tetap nocount aktif, kecuali ketika Anda benar-benar mengembalikan resultset". Saya tidak tahu cara apa pun untuk memecahkan kode klien apa pun, itu berarti kode klien tidak perlu tahu apa-apa tentang internal proc, dan itu tidak terlalu memberatkan.
sumber
Mengenai pemicu melanggar NHibernate, saya memiliki pengalaman itu secara langsung. Pada dasarnya, ketika NH melakukan UPDATE, ia mengharapkan sejumlah baris yang terpengaruh. Dengan menambahkan SET NOCOUNT ON ke pemicu Anda mendapatkan jumlah baris kembali ke apa yang diharapkan NH sehingga memperbaiki masalah. Jadi ya, saya pasti akan merekomendasikan mematikannya untuk pemicu jika Anda menggunakan NH.
Mengenai penggunaan dalam SP, itu masalah preferensi pribadi. Saya selalu mematikan hitungan baris, tetapi sekali lagi, tidak ada argumen yang kuat.
Pada catatan yang berbeda, Anda harus benar-benar mempertimbangkan untuk pindah dari arsitektur berbasis SP, maka Anda bahkan tidak akan memiliki pertanyaan ini.
sumber
Saya ingin memverifikasi diri saya bahwa 'SET NOCOUNT ON' tidak menyimpan paket jaringan atau pulang-pergi
Saya menggunakan tes SQLServer 2017 pada host lain (saya menggunakan VM)
create table ttable1 (n int); insert into ttable1 values (1),(2),(3),(4),(5),(6),(7) go
create procedure procNoCount as begin set nocount on update ttable1 set n=10-n end
create procedure procNormal as begin update ttable1 set n=10-n end
Kemudian saya melacak paket pada port 1433 dengan alat 'Wireshark': tombol 'capture filter' -> 'port 1433'exec procNoCount
ini adalah paket respons:
0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 42 d0 ce 40 00 40 06 84 0d c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e5 9c be fb 85 01 50 18 0030 02 b4 e6 0e 00 00 04 01 00 1a 00 35 01 00 79 00 0040 00 00 00 fe 00 00 e0 00 00 00 00 00 00 00 00 00
exec procNormal
ini adalah paket respons:
0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 4f d0 ea 40 00 40 06 83 e4 c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e8 b1 be fb 8a 35 50 18 0030 03 02 e6 1b 00 00 04 01 00 27 00 35 01 00 ff 11 0040 00 c5 00 07 00 00 00 00 00 00 00 79 00 00 00 00 0050 fe 00 00 e0 00 00 00 00 00 00 00 00 00
Pada baris 40 saya dapat melihat '07' yang merupakan jumlah 'baris yang terpengaruh'. Itu termasuk dalam paket respons. Tidak ada paket tambahan.
Namun memiliki 13 byte tambahan yang dapat disimpan, tetapi mungkin tidak sepadan dengan mengurangi nama kolom (mis. 'Mengelola Departemen' menjadi 'MD')
Jadi saya tidak melihat alasan untuk menggunakannya untuk kinerja
NAMUN Seperti yang disebutkan orang lain itu bisa memecahkan ADO.NET dan saya juga menemukan masalah menggunakan python: MSSQL2008 - Pyodbc - SQL sebelumnya bukan permintaan
Jadi mungkin kebiasaan yang baik masih ...
sumber
Baris kode ini digunakan dalam SQL untuk tidak mengembalikan baris nomor yang terpengaruh dalam pelaksanaan kueri. Jika kami tidak membutuhkan jumlah baris yang terpengaruh, kami dapat menggunakan ini karena ini akan membantu menghemat penggunaan memori dan meningkatkan kecepatan pelaksanaan kueri.
sumber
SET NOCOUNT AKTIF; Kode di atas akan menghentikan pesan yang dihasilkan oleh mesin server sql ke jendela hasil yang digawangi setelah eksekusi perintah DML / DDL.
Kenapa kita melakukannya? Karena mesin server SQL membutuhkan sumber daya untuk mendapatkan status dan menghasilkan pesan, itu dianggap sebagai beban berlebihan ke mesin server Sql.
sumber
Satu tempat yang
SET NOCOUNT ON
bisa sangat membantu adalah tempat Anda melakukan kueri dalam satu lingkaran atau kursor. Ini dapat menambah banyak lalu lintas jaringan.Mengaktifkan statistik klien di SSMS, serangkaian
EXEC NoCountOn
danEXEC NoCountOff
menunjukkan bahwa ada lalu lintas tambahan 390KB di NoCountOff yang satu:Mungkin tidak ideal untuk melakukan kueri dalam satu lingkaran atau kursor, tetapi kita juga tidak hidup di dunia ideal :)
sumber
Saya tahu itu pertanyaan yang cukup lama. tetapi hanya untuk pembaruan.
Cara terbaik untuk menggunakan "SET NOCOUNT ON" adalah dengan memasangnya sebagai pernyataan pertama dalam SP Anda dan mengaturnya MATI lagi tepat sebelum pernyataan SELECT terakhir.
sumber
Saya tidak tahu cara menguji SET NOCOUNT ON antara klien dan SQL, jadi saya menguji perilaku serupa untuk perintah SET lainnya "SET TINGKAT ISOLASI TRANSAKSI BACA BACA TIDAK DIKETAHUI"
Saya mengirim perintah dari koneksi saya untuk mengubah perilaku standar SQL (READ COMMITTED), dan itu diubah untuk perintah selanjutnya. Ketika saya mengubah level ISOLASI di dalam prosedur tersimpan, itu tidak mengubah perilaku koneksi untuk perintah berikutnya.
Kesimpulan saat ini,
Saya pikir ini relevan dengan perintah SET lainnya seperti "SET NOCOUNT ON"
sumber
NOCOUNT
if (set no count == off)
{maka ia akan menyimpan data tentang berapa banyak catatan yang terpengaruh sehingga mengurangi kinerja} selain itu {itu tidak akan melacak catatan perubahan karenanya meningkatkan kinerja}}
sumber
Kadang-kadang bahkan hal-hal paling sederhana pun dapat membuat perbedaan. Salah satu item sederhana yang harus menjadi bagian dari setiap prosedur tersimpan adalah
SET NOCOUNT ON
. Baris kode yang satu ini, diletakkan di bagian atas prosedur yang tersimpan mematikan pesan yang SQL Server kirim kembali ke klien setelah setiap pernyataan T-SQL dijalankan. Ini dilakukan untuk semuaSELECT
,INSERT
,UPDATE
, danDELETE
pernyataan. Memiliki informasi ini berguna ketika Anda menjalankan pernyataan T-SQL di jendela kueri, tetapi ketika prosedur yang tersimpan dijalankan tidak perlu informasi ini diteruskan kembali ke klien.Dengan menghapus overhead tambahan ini dari jaringan, ini dapat sangat meningkatkan kinerja keseluruhan untuk database dan aplikasi Anda.
Jika Anda masih perlu mendapatkan jumlah baris yang dipengaruhi oleh pernyataan T-SQL yang mengeksekusi Anda masih bisa menggunakan
@@ROWCOUNT
opsi. Dengan mengeluarkanSET NOCOUNT ON
fungsi ini (@@ROWCOUNT
) masih berfungsi dan masih dapat digunakan dalam prosedur tersimpan Anda untuk mengidentifikasi berapa banyak baris yang dipengaruhi oleh pernyataan.sumber