Apakah ekspresi boolean dalam SQL WHERE klausa hubung singkat dievaluasi ?
Sebagai contoh:
SELECT *
FROM Table t
WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key)
Jika @key IS NULL bernilai true, apakah @key TIDAK NULL AND @key = t.Key dievaluasi?
Jika Tidak, mengapa tidak?
Jika Ya, apakah dijamin? Apakah ini bagian dari ANSI SQL atau spesifik database?
Jika basis data spesifik, SqlServer? Peramal? MySQL?
sql
short-circuiting
Greg Dean
sumber
sumber
WHERE a = 1 AND b = 2
itu bisa efisien untuk mesin database untuk menemukan semua baris di mana b = 2 pertama, kemudian filter di mana a = 1. Jika Anda meminta jaminan maka optimizer menjadi tidak berguna.Jawaban:
ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf
sumber
CASE
hubung pendek.Dari penjelasan di atas, hubungan arus pendek tidak tersedia.
Jika Anda membutuhkannya, saya sarankan pernyataan Kasus:
Expr1
selalu dievaluasi, tetapi hanya satuExpr2
danExpr3
akan dievaluasi per baris.sumber
Saya pikir ini adalah salah satu kasus di mana saya akan menulisnya seolah-olah tidak korsleting, karena tiga alasan.
Karena untuk MSSQL, itu tidak diselesaikan dengan melihat BOL di tempat yang jelas, jadi bagi saya, yang membuatnya ambigu secara kanonik.
karena setidaknya saya tahu kode saya akan berfungsi. Dan yang lebih penting, begitu juga mereka yang datang setelah saya, jadi saya tidak mengatur mereka untuk khawatir melalui pertanyaan yang sama berulang kali.
Saya cukup sering menulis untuk beberapa produk DBMS, dan saya tidak ingin harus mengingat perbedaannya jika saya dapat mengatasinya dengan mudah.
sumber
Saya tidak percaya bahwa hubungan arus pendek di SQL Server (2005) dijamin. SQL Server menjalankan kueri Anda melalui algoritme pengoptimalannya yang memperhitungkan banyak hal (indeks, statistik, ukuran tabel, sumber daya, dll.) Untuk menghasilkan rencana eksekusi yang efektif. Setelah evaluasi ini, Anda tidak dapat mengatakan dengan pasti bahwa logika korsleting Anda dijamin.
Saya mengalami pertanyaan yang sama beberapa waktu yang lalu dan penelitian saya benar-benar tidak memberi saya jawaban yang pasti. Anda dapat menulis kueri kecil untuk memberi Anda rasa pembuktian bahwa itu berfungsi tetapi dapatkah Anda yakin bahwa ketika beban pada basis data Anda meningkat, tabel-tabel tumbuh menjadi lebih besar, dan berbagai hal dioptimalkan dan diubah dalam database, kesimpulan itu akan memegang. Saya tidak bisa dan karena itu berbuat salah di sisi hati-hati dan menggunakan KASUS dalam klausa WHERE untuk memastikan hubungan pendek.
sumber
Anda harus mengingat cara kerja database. Dengan kueri parameter, db membuat rencana eksekusi berdasarkan kueri tanpa nilai parameter. Kueri ini digunakan setiap kali kueri dijalankan terlepas dari apa nilai yang sebenarnya disediakan. Apakah hubung-pendek kueri dengan nilai-nilai tertentu tidak akan berpengaruh pada rencana eksekusi.
sumber
Saya biasanya menggunakan ini untuk parameter opsional. Apakah ini sama dengan hubungan arus pendek?
Ini memberi saya opsi untuk lulus -1 atau apa pun untuk menjelaskan pemeriksaan opsional atribut. Kadang-kadang ini melibatkan bergabung di beberapa tabel, atau lebih disukai tampilan.
Sangat praktis, tidak sepenuhnya yakin akan kerja ekstra yang diberikannya pada mesin db.
sumber
Untuk SQL Server, saya pikir itu tergantung pada versi tetapi pengalaman saya dengan SQL Server 2000 adalah bahwa ia masih mengevaluasi @key = t.Key bahkan ketika @key adalah nol. Dengan kata lain, itu tidak melakukan hubungan arus pendek yang efisien ketika mengevaluasi klausa WHERE.
Saya telah melihat orang merekomendasikan struktur seperti contoh Anda sebagai cara melakukan kueri fleksibel tempat pengguna dapat memasukkan atau tidak memasukkan berbagai kriteria. Pengamatan saya adalah bahwa Key masih terlibat dalam rencana permintaan ketika @key adalah null dan jika Key diindeks maka itu tidak menggunakan indeks secara efisien.
Jenis permintaan fleksibel dengan beragam kriteria ini mungkin merupakan satu kasus di mana SQL yang dibuat secara dinamis benar-benar cara terbaik. Jika @key adalah null maka Anda sama sekali tidak memasukkannya ke dalam kueri.
sumber
Baru saja menemukan pertanyaan ini, dan sudah menemukan entri blog ini: http://rusanu.com/2009/09/13/on-sql-server-boolean-operator-short-circuit/
Server SQL bebas untuk mengoptimalkan kueri di mana saja ia mau, jadi dalam contoh yang diberikan di posting blog, Anda tidak dapat mengandalkan korsleting.
Namun, KASUS tampaknya didokumentasikan untuk mengevaluasi dalam urutan tertulis - periksa komentar dari posting blog itu.
sumber
Karakteristik utama dari evaluasi hubung singkat adalah bahwa ia berhenti mengevaluasi ekspresi segera setelah hasilnya dapat ditentukan. Itu berarti bahwa sisa ekspresi dapat diabaikan karena hasilnya akan sama terlepas apakah itu dievaluasi atau tidak.
Operator boolean biner bersifat komutatif, artinya:
jadi tidak ada jaminan dalam urutan evaluasi. Urutan evaluasi akan ditentukan oleh pengoptimal permintaan.
Dalam bahasa dengan objek mungkin ada situasi di mana Anda dapat menulis ekspresi boolean yang hanya dapat dievaluasi dengan evaluasi hubung singkat. Konstruksi kode sampel Anda sering digunakan dalam bahasa seperti itu (C #, Delphi, VB). Sebagai contoh:
Contoh C # ini akan menyebabkan pengecualian jika
someString == null
karena itu akan sepenuhnya dievaluasi. Dalam evaluasi hubung singkat, ini akan bekerja setiap saat.SQL hanya beroperasi pada variabel skalar (tidak ada objek) yang tidak dapat diinisialisasi, sehingga tidak ada cara untuk menulis ekspresi boolean yang tidak dapat dievaluasi. Jika Anda memiliki beberapa nilai NULL, perbandingan apa pun akan menghasilkan false.
Itu berarti bahwa dalam SQL Anda tidak dapat menulis ekspresi yang dievaluasi secara berbeda tergantung pada penggunaan hubung singkat atau evaluasi penuh.
Jika implementasi SQL menggunakan evaluasi hubung singkat, diharapkan hanya dapat mempercepat eksekusi permintaan.
sumber
saya tidak tahu tentang hubungan pendek, tetapi saya akan menuliskannya sebagai pernyataan if-else
juga, variabel harus selalu berada di sisi kanan persamaan. ini membuatnya masuk akal.
http://en.wikipedia.org/wiki/Sargable
sumber
Di bawah tes cepat dan kotor pada SQL Server 2008 R2:
Ini segera kembali tanpa catatan. Jenis perilaku hubung singkat hadir.
Kemudian coba ini:
mengetahui tidak ada catatan akan memenuhi kondisi ini:
Ini memakan waktu beberapa detik, menunjukkan perilaku hubung singkat tidak ada lagi dan operasi kompleks sedang dievaluasi untuk setiap catatan.
Semoga ini bisa membantu kalian.
sumber
Berikut ini adalah demo untuk membuktikan bahwa MySQL melakukan hubung singkat klausa WHERE :
http://rextester.com/GVE4880
Ini menjalankan kueri berikut:
Satu-satunya perbedaan antara ini adalah urutan operan dalam kondisi OR.
myslowfunction
sengaja tidur sebentar dan memiliki efek samping menambahkan entri ke tabel log setiap kali dijalankan. Berikut adalah hasil dari apa yang dicatat ketika menjalankan dua pertanyaan di atas:Di atas menunjukkan bahwa fungsi lambat dieksekusi lebih sering ketika muncul di sisi kiri kondisi ATAU ketika operan lain tidak selalu benar (karena hubungan arus pendek).
sumber
Ini membutuhkan tambahan 4 detik dalam penganalisis kueri, jadi dari apa yang saya lihat JIKA bahkan tidak disingkat ...
Alangkah baiknya memiliki cara yang terjamin!
sumber
Sangat jelas bahwa server MS Sql mendukung teori hubung singkat, untuk meningkatkan kinerja dengan menghindari pemeriksaan yang tidak perlu,
Contoh Pendukung:
Di sini, contoh pertama akan menghasilkan kesalahan 'Konversi gagal saat mengubah nilai varchar' A 'ke int tipe data.'
Sedangkan yang kedua berjalan dengan mudah karena kondisi 1 = 1 dievaluasi ke TRUE dan dengan demikian kondisi kedua tidak berjalan sama sekali.
Lebih jauh lagi
di sini kondisi pertama akan dinilai false dan karenanya DBMS akan pergi untuk kondisi kedua dan sekali lagi Anda akan mendapatkan kesalahan konversi seperti pada contoh di atas.
CATATAN: SAYA MENULIS KONDISI KESALAHAN HANYA UNTUK MEWUJUDKAN CUACA KONDISI INI DILAKSANAKAN ATAU BERLINGKAR-SINGKAT JIKA HASIL HASIL DALAM KESALAHAN BERARTI KONDISI YANG DILAKSANAKAN, KONDISI DILAKUKAN DENGAN SINGKAT, SINGKAT-SINGKAT.
PENJELASAN SEDERHANA
Mempertimbangkan,
karena kondisi pertama sedang dievaluasi menjadi BENAR , tidak ada artinya untuk mengevaluasi kondisi kedua karena evaluasi dalam nilai apa pun tidak akan mempengaruhi hasil sama sekali, sehingga peluang yang baik bagi Sql Server untuk menghemat waktu Eksekusi Kueri dengan melewatkan pemeriksaan atau evaluasi kondisi yang tidak perlu .
dalam hal "ATAU" jika kondisi pertama dievaluasi ke TRUE seluruh rantai yang dihubungkan oleh "ATAU" akan dianggap dievaluasi dengan benar tanpa mengevaluasi yang lain.
jika kondisi1 dievaluasi menjadi benar, istirahatkan semua kondisi sampai kondisiN akan dilewati. Dengan kata-kata umum pada penentuan TRUE pertama , semua kondisi lain yang dihubungkan oleh OR akan dilewati.
Pertimbangkan kondisi kedua
karena kondisi pertama sedang dievaluasi ke FALSE dievaluasi tidak ada artinya untuk mengevaluasi kondisi kedua karena evaluasi dalam nilai apa pun tidak akan mempengaruhi hasilnya sama sekali, jadi sekali lagi kesempatan yang baik untuk Sql Server untuk menghemat waktu Eksekusi Query dengan melewatkan pemeriksaan atau evaluasi kondisi yang tidak perlu .
dalam kasus "DAN" jika kondisi pertama dievaluasi menjadi SALAH seluruh rantai yang terhubung dengan "DAN" akan dianggap sebagai dievaluasi ke SALAH tanpa mengevaluasi yang lain.
jika condition1 dievaluasi menjadi FALSE , istirahatkan semua kondisi sampai conditionN akan dilewati. Dengan kata-kata umum pada penentuan FALSE pertama , semua kondisi lain yang ditautkan oleh AND akan dilewati.
OLEH KARENA ITU, PROGRAMER BIJAK HARUS SELALU MEMPROGRAM RANTAI KONDISI SEPERTI YANG, KURANGNYA MURNI ATAU KONDISI YANG PALING MENGHAPUS DITERAPKAN PERTAMA, ATAU MENGATUR KETENTUAN DALAM SEPERTI YANG BISA DIBUTUHKAN.
sumber