Perbedaan kinerja untuk COALESCE versus ISNULL?

48

Saya telah melihat banyak orang menggunakan fungsi COALESCE menggantikan ISNULL. Dari pencarian internet, saya telah menemukan bahwa COALESCE adalah standar ANSI, jadi ada keuntungan yang kita tahu apa yang diharapkan ketika menggunakannya. Namun, ISNULL tampaknya lebih mudah dibaca karena tampaknya lebih jelas apa yang dilakukannya.

Saya juga menyadari bahwa ISNULL agak rumit karena bertindak berbeda pada server basis data yang berbeda dan dalam bahasa yang berbeda.

Semua itu, dalam pikiran saya, bermuara pada gaya dan standar. Mengingat gaya itu subjektif, apakah ada alasan untuk menggunakan COALESCE di atas ISNULL (atau sebaliknya)? Secara khusus, apakah ada keunggulan kinerja satu di atas yang lain?

Richard
sumber
1
Saya tidak melihat disebutkan dalam salah satu jawaban bahwa sub kueri dalam COALESCE dievaluasi dua kali.
Martin Smith
4
"ISNULL sepertinya lebih mudah dibaca karena tampaknya lebih jelas apa yang dilakukannya" - sungguh? Saya menemukan nama counter-unintuitive: Saya akan mengharapkannya untuk mengembalikan Boolean yang menunjukkan apakah ekspresi diselesaikan menjadi nol atau tidak diketahui. Nama COALESCEitu hanya tidak intuitif;)
onedaywhen

Jawaban:

26

COALESCEditerjemahkan secara internal ke CASEekspresi, ISNULLadalah fungsi mesin internal.

COALESCEadalah fungsi standar ANSI, ISNULLadalah T-SQL.

Perbedaan kinerja dapat dan memang muncul ketika pilihan mempengaruhi rencana eksekusi tetapi perbedaan dalam kecepatan fungsi mentah sangat kecil .

Mark Storey-Smith
sumber
40
  • ISNULL khusus untuk Sybase / SQL Server
  • COALESCE bersifat portabel

Kemudian

  • ISNULL mengambil 2 argumen
  • COALESCE mengambil argumen 1-n

Akhirnya, dan sedikit kesenangan. Datatype hasil dan panjang / presisi / skala

  • ISNULL sama dengan argumen pertama
  • COALESCE adalah yang tertinggi menurut prioritas datatype

Bit terakhir ini adalah mengapa ISNULL biasanya digunakan karena lebih dapat diprediksi (?) Dan COALESCE dapat menambahkan konversi tipe data yang tidak diinginkan: dari sinilah bit "lebih lambat" berasal

DECLARE @len10 varchar(10); --leave it NULL
SELECT
    ISNULL(@len10, '0123456789ABCDEF'),     -- gives 0123456789
    COALESCE(@len10, '0123456789ABCDEF');   -- gives 0123456789ABCDEF

Semua tipe data sama, Anda tidak akan melihat perbedaan praktis ...

gbn
sumber
22

Seperti yang ditunjukkan oleh Mark, Anda akan kesulitan menemukan perbedaan kinerja; Saya pikir faktor lain akan lebih penting. Bagi saya, saya selalu menggunakan COALESCE, dan sebagian besar sudah disebutkan oleh Anda atau Tandai:

  • COALESCE adalah standar ANSI. Satu hal yang kurang perlu saya khawatirkan jika saya akan mem-porting kode saya. Bagi saya pribadi ini tidak begitu penting, karena saya tahu betapa jarang port seperti itu benar-benar terjadi di luar dunia kelas Celko, tetapi bagi sebagian orang ini adalah keuntungan.
  • Berlawanan dengan apa yang Anda katakan tentang keterbacaan, saya merasa bisa lebih sulit untuk membaca ISNULL terutama untuk pengguna yang berasal dari bahasa lain atau platform di mana ISNULL mengembalikan boolean (yang tidak ada dalam SQL Server). Memang, COALESCE lebih sulit dieja, tetapi setidaknya itu tidak mengarah pada asumsi yang salah.
  • COALESCE jauh lebih fleksibel, seperti yang bisa saya katakan COALESCE (a, b, c, d) sedangkan dengan ISNULL saya harus melakukan banyak bersarang untuk mencapai hal yang sama.

Anda juga harus yakin mengetahui bagaimana presedensi tipe data ditangani menggunakan dua fungsi jika Anda menggunakannya dengan tipe data yang berbeda / precision dll.

Catatan

Ada satu pengecualian. Ini ditangani secara berbeda dalam versi SQL Server saat ini:

SELECT COALESCE((SELECT some_aggregate_query),0); 

SELECT ISNULL((SELECT some_aggregate_query),0); 

The COALESCEvarian benar-benar akan mengeksekusi some_aggregate_querydua kali (sekali untuk memeriksa nilai, dan sekali untuk kembali ketika non-nol), sementara ISNULLhanya akan mengeksekusi subquery sekali. Saya berbicara tentang beberapa perbedaan lain di sini:

Aaron Bertrand
sumber