Pikiran pertama saya di sini adalah -- apa masalah kinerjanya? Tentu Anda memiliki loop (sekali per baris untuk diterapkan di mana) di dalam loop yang menjalankan kueri. Tetapi apakah Anda mendapatkan rencana eksekusi yang buruk? Apakah hasil Anda set besar? Tapi mari kita beralih ke generik. Bagaimana sekali memecahkan masalah ini? SQL tidak benar-benar melakukan memoisasi (seperti yang ditunjukkan oleh @Martin_Smith yang terkenal). Jadi apa yang harus dilakukan anak laki-laki?
Opsi 1 - Desain Baru
Buat desain yang sama sekali baru. Dalam kasus khusus ini @Aaron_Bertrand menunjukkan bahwa tabel kalender dapat memenuhi kebutuhan Anda. Cukup benar. Ini tidak benar-benar membantu Anda dengan situasi non-kalender, tetapi seperti yang sering terjadi di SQL, Anda perlu berpikir sedikit berbeda.
Opsi 2 - Lebih Sedikit Menghubungi UDF
Persempit kumpulan item yang memanggil fungsi ini. Ini mengingatkan saya banyak tentang bagaimana melakukan penghitungan paging/baris . Hasilkan kumpulan hasil kecil yang memiliki nilai berbeda yang diperlukan lalu panggil UDF Anda sehingga hanya dipanggil beberapa kali. Ini mungkin atau mungkin bukan pilihan, tetapi dapat bekerja dalam banyak skenario.
Opsi 3 - UDF Dinamis
Saya mungkin akan dicemooh karena saran ini, tapi begini. Apa yang membuat UDF ini lambat adalah pernyataan pilih di dalam loop. Jika meja Liburan Anda benar-benar jarang berubah, Anda bisa meletakkan pemicu di atas meja. Pemicu akan menulis dan memperbarui UDF. UDF baru bisa memaksa semua keputusan liburan. Apakah sedikit seperti kanibalisme dengan SQL menulis SQL? Tentu. Tapi itu akan menyingkirkan sub-permintaan dan mempercepat UDF. Biarkan ejekan dimulai.
Opsi 4 - Ingat!
Meskipun SQL tidak dapat langsung memoize, kami memiliki SQL CLR. Ubah UDF menjadi udf SQL CLR. Di CLR Anda bisa menggunakan variabel statis. Anda dapat dengan mudah mengambil tabel Holidays pada interval reguler dan menyimpannya dalam tabel hash. Kemudian tulis ulang loop Anda di CLR. Anda bahkan dapat melangkah lebih jauh dan mencatat seluruh jawaban jika itu logika yang tepat.
Pembaruan:
Opsi 1 - Saya benar-benar mencoba untuk fokus pada yang umum di sini, bukan fungsi contoh yang Anda gunakan di atas. Namun, desain UDF Anda saat ini memungkinkan beberapa panggilan ke tabel Liburan jika Anda melakukan beberapa panggilan berturut-turut. Menggunakan semacam tabel bergaya kalender yang berisi daftar 'hari buruk' dan 'hari kerja berikutnya' yang sesuai akan memungkinkan Anda menghapus potensi beberapa klik &kueri.
Opsi 3 - Meskipun domain tidak diketahui sebelumnya, Anda dapat memodifikasi tabel liburan Anda dengan sangat baik. Untuk hari libur tertentu itu akan berisi hari kerja yang sesuai berikutnya. Dari data ini Anda dapat mengeluarkan UDF dengan pernyataan kasus yang panjang (ketika '5/5/2012' lalu '14/05/2012' atau yang serupa) di bagian bawah. Strategi ini mungkin tidak bekerja untuk setiap jenis masalah, tetapi dapat bekerja dengan baik untuk beberapa jenis masalah.
Opsi 4 - Ada implikasi untuk setiap teknologi. CLR perlu dikerahkan, konfigurasi SQL Server dimodifikasi dan SQL CLR terbatas pada kerangka 3.5. Secara pribadi, saya menemukan penyesuaian ini cukup mudah, tetapi situasi Anda mungkin berbeda (katakanlah DBA bandel, atau pembatasan modifikasi pada server produksi).
Menggunakan variabel statis memerlukan rakitan menjadi diberikan KEPERCAYAAN LENGKAP . Anda harus memastikan penguncian Anda benar.
Ada beberapa bukti bahwa pada sangat tinggi tingkat transaksi CLR tidak berkinerja sebaik SQL langsung. Namun, dalam skenario Anda, pengamatan ini mungkin tidak berlaku karena tidak ada korelasi SQL langsung untuk apa yang Anda coba lakukan (memoize).