Telah disarankan kepada saya bahwa penggunaan pernyataan IF dalam t-SQL batch merusak kinerja. Saya mencoba mencari konfirmasi atau memvalidasi pernyataan ini. Saya menggunakan SQL Server 2005 dan 2008.
Penegasannya adalah bahwa dengan kumpulan berikut: -
IF @parameter = 0
BEGIN
SELECT ... something
END
ELSE
BEGIN
SELECT ... something else
END
SQL Server tidak dapat menggunakan kembali rencana eksekusi yang dihasilkan karena eksekusi berikutnya mungkin memerlukan cabang yang berbeda. Ini menyiratkan bahwa SQL Server akan menghilangkan satu cabang sepenuhnya dari rencana eksekusi atas dasar bahwa untuk pelaksanaan saat ini sudah dapat menentukan cabang mana yang diperlukan. Apakah ini benar?
Selain itu apa yang terjadi dalam kasus ini: -
IF EXISTS (SELECT ....)
BEGIN
SELECT ... something
END
ELSE
BEGIN
SELECT ... something else
END
di mana tidak mungkin untuk menentukan terlebih dahulu cabang mana yang akan dieksekusi?
sql-server
sql-server-2008
sql-server-2005
query-performance
AnthonyWJones
sumber
sumber
Jawaban:
SQL Server mengoptimalkan proses kompilasi rencana kueri untuk prosedur tersimpan dengan mengabaikan cabang bersyarat di dalam prosedur tersimpan. Rencananya akan dihasilkan berdasarkan parameter yang digunakan untuk eksekusi pertama, ini akan menyebabkan masalah jika parameter berbeda untuk cabang.
Saya akan menempatkan SQL untuk masing-masing cabang ke dalam prosedur tersimpan mereka sendiri, sehingga rencana yang dihasilkan didasarkan pada penggunaan aktual parameter untuk cabang itu.
sumber
Satu-satunya jalan pintas adalah
IF 1 = 1
@Parameter dan EXISTS masih memerlukan pemrosesan untuk "kasus umum" (
@parameter = 42
katakanlah)Mengatakan itu ... apa yang dikatakan rencana eksekusi yang sebenarnya serta profiler yang menangkap peristiwa rekomplisi? (Saya tidak suka rencana yang diperkirakan sesuai jawaban Jao)
sumber
Cobalah untuk menampilkan perkiraan rencana eksekusi, bukan yang sebenarnya. Anda akan melihat bahwa yang pertama berisi
COND
operator.Operator ini juga termasuk dalam rencana eksekusi yang di-cache. Dalam contoh Anda, rencana pengecualian akan berisi satu operator COND dan 2 cabang SELECT dan karenanya akan sepenuhnya dapat digunakan kembali. Karena ketika menjalankan batch SQL Server mengevaluasi tidak hanya pernyataan DML tetapi semua lainnya juga, mendapatkannya dari paket.
Rencana pelaksanaan internal adalah struktur yang mirip dengan pohon ekspresi.
sumber
Paket akan dibuat berdasarkan parameter yang dilewati sehingga pada kenyataannya saya katakan Tidak - memiliki logika kondisional yang biasanya didasarkan pada parameter tidak merusak kinerja.
Anda akan mendapatkan beberapa paket yang dihasilkan, dengan asumsi parameter menyebabkan varians yang cukup untuk diperhatikan oleh optimizer kueri.
Anda dapat melihat yang mana dengan mengaktifkan rencana Tampilkan Eksekusi, menjalankan skrip - perhatikan perbedaan dalam rencana tersebut. Ketika Anda menjalankan prosedur (saya mengasumsikan prosedur tersimpan di sini), Anda akan melihat pertama kali umumnya lebih cepat, hit kedua menggunakan rencana tersimpan. Ubah parameter dan ulangi kemudian jalankan parameter asli - dalam teori rencananya masih akan di cache tetapi itu tergantung pada penggunaan server (tick cache - mereka tidak tinggal selamanya ..) dll.
sumber
Mungkin ini telah ditingkatkan pada tahun 2005 dan 2008, tetapi menggunakan kondisional pada tahun 2000 akan lebih buruk daripada yang Anda gambarkan, ini akan menyusun rencana untuk menangani proses prosedur pertama dan kemudian menggunakan rencana itu untuk menjalankan prosedur bahkan ketika kondisinya berubah. Dalam pengalaman saya ini menyebabkan pertanyaan yang berjalan dalam hitungan menit berjalan dalam hitungan jam. Meskipun saya menggunakan 2008 sekarang dan telah menggunakan 2005 saya tidak bisa mengomentari tentang bagaimana coditional bekerja di sana karena saya tidak lagi menggunakannya.
sumber