Първата ми мисъл тук е -- какъв е проблемът с производителността? Разбира се, че имате цикъл (веднъж на ред, за да приложите къде) в рамките на цикъл, който изпълнява заявка. Но получавате ли лоши планове за изпълнение? Огромни ли са вашите резултати? Но нека се обърнем към генеричните. Как веднъж се решава този проблем? SQL всъщност не прави мемоизация (както отбелязва известният @Martin_Smith). И така, какво да прави едно момче?
Вариант 1 - Нов дизайн
Създайте изцяло нов дизайн. В този конкретен случай @Aaron_Bertrand посочва, че календарна таблица може да отговори на вашите нужди. Съвсем правилно. Това всъщност не ви помага в ситуации извън календара, но както често се случва в SQL, трябва да мислите малко по-различно.
Вариант 2 - Обадете се на UDF Less
Стеснете набора от елементи, които извикват тази функция. Това много ми напомня как да направя успешен странициране/броене на редове . Генерирайте малък набор от резултати, който има необходимите различни стойности и след това обадете се на вашия UDF, така че да бъде извикан само няколко пъти. Това може или не може да е опция, но може да работи в много сценарии.
Вариант 3 - Динамичен UDF
Вероятно ще ме освиркват от стаята за това предложение, но ето го. Това, което прави този UDF бавен, е командата select вътре в цикъла. Ако вашата празнична трапеза наистина се променя рядко, можете да поставите задействане на масата. Тригерът ще изпише и актуализира UDF. Новото СДС можеше да налага грубо всички ваканционни решения. Ще бъде ли малко като канибализъм с SQL, който пише SQL? Сигурен. Но ще се отърве от подзаявката и ще ускори UDF. Нека подмятането започне.
Вариант 4 – Запомнете го!
Докато SQL не може директно да мемоизира, ние имаме SQL CLR. Преобразувайте UDF в SQL CLR udf. В CLR можете да използвате статични променливи. Можете лесно да вземете празничната таблица на някакъв редовен интервал и да ги съхраните в хеш-таблица. След това просто пренапишете своя цикъл в CLR. Можете дори да отидете по-далеч и да запомните целия отговор, ако това е подходяща логика.
Актуализация:
Вариант 1 - наистина се опитвах да се съсредоточа върху общото тук, а не върху примерната функция, която използвахте по-горе. Текущият дизайн на вашия UDF обаче позволява множество извиквания към празничната маса, ако случайно уцелите няколко подред. Използването на някакъв вид таблица в стил календар, която съдържа списък с „лоши дни“ и съответния „следващ работен ден“, ще ви позволи да премахнете потенциала за множество посещения и заявки.
Вариант 3 – Докато домейнът е неизвестен преди време, можете много добре да промените празничната си маса. За даден празничен ден ще съдържа следващия съответен работен ден. От тези данни можете да изплюете UDF с дълъг оператор (когато е „5/5/2012“, след това „5/14/2012“ или нещо подобно) в долната част. Тази стратегия може да не работи за всеки тип проблем, но може да работи добре за някои видове проблеми.
Вариант 4 – Има последици за всяка технология. CLR трябва да бъде внедрен, конфигурацията на SQL Server модифицирана и SQL CLR е ограничен до рамката 3.5. Лично аз намерих тези корекции за достатъчно лесни, но вашата ситуация може да е различна (да речем непокорен DBA или ограничения за модификации на производствени сървъри).
Използването на статични променливи изисква сглобките да бъдат предоставено ПЪЛНО ДОВЕРИЕ . Ще трябва да се уверите, че заключвате правилно.
Има някои доказателства че при много високо нива на транзакция CLR не работи толкова добре, колкото директния SQL. Във вашия сценарий обаче това наблюдение може да не е приложимо, защото няма пряка SQL корелация за това, което се опитвате да направите (запаметяване).