Menggunakan JIKA di T-SQL melemahkan atau merusak caching rencana eksekusi?

20

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?

AnthonyWJones
sumber
1
SQL Server dapat dan tidak menggunakan kembali rencana eksekusi karena tidak mempertimbangkan cabang, hanya pernyataan yang terkandung dalam cabang.
MartinC

Jawaban:

10

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.

MartinC
sumber
6

Satu-satunya jalan pintas adalah IF 1 = 1

@Parameter dan EXISTS masih memerlukan pemrosesan untuk "kasus umum" ( @parameter = 42katakanlah)

Mengatakan itu ... apa yang dikatakan rencana eksekusi yang sebenarnya serta profiler yang menangkap peristiwa rekomplisi? (Saya tidak suka rencana yang diperkirakan sesuai jawaban Jao)

gbn
sumber
3

Cobalah untuk menampilkan perkiraan rencana eksekusi, bukan yang sebenarnya. Anda akan melihat bahwa yang pertama berisi CONDoperator.

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.

Tom V - Tim Monica
sumber
0

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.

Barry King
sumber
0

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
2
2005+ memiliki kompilasi tingkat pernyataan sehingga Anda tidak lagi memiliki "satu paket per sp"
gbn