Moja pierwsza myśl tutaj jest -- na czym polega problem z wydajnością? Na pewno masz pętlę (raz na wiersz, aby zastosować gdzie) w pętli, która uruchamia zapytanie. Ale czy masz słabe plany egzekucyjne? Czy Twoje zestawy wyników są ogromne? Ale przejdźmy do ogólnych. Jak raz rozwiązuje ten problem? SQL tak naprawdę nie wykonuje memoization (jak wskazuje znany @Martin_Smith). Więc co ma zrobić chłopiec?
Opcja 1 – Nowy projekt
Stwórz zupełnie nowy projekt. W tym konkretnym przypadku @Aaron_Bertrand wskazuje, że tabela kalendarza może spełnić Twoje potrzeby. Całkiem dobrze. To naprawdę nie pomaga w sytuacjach niezwiązanych z kalendarzem, ale jak to często bywa w SQL, musisz myśleć nieco inaczej.
Opcja 2 – Zadzwoń do UDF mniej
Zawęź zestaw elementów, które wywołują tę funkcję. To bardzo mi przypomina, jak zrobić udany stronicowanie/liczenie wierszy . Wygeneruj mały zestaw wyników, który ma różne wymagane wartości a następnie zadzwoń do swojego UDF, aby był wywoływany tylko kilka razy. Może to być opcja, ale nie musi, ale może działać w wielu scenariuszach.
Opcja 3 – Dynamiczny UDF
Prawdopodobnie zostanę wygwizdany z pokoju za tę sugestię, ale tutaj jest. To, co spowalnia ten UDF, to instrukcja select wewnątrz pętli. Jeśli Twój świąteczny stół naprawdę rzadko się zmienia, możesz postawić na stole wyzwalacz. Wyzwalacz wypisze i zaktualizuje UDF. Nowy UDF mógłby brutalnie wymusić wszystkie wakacyjne decyzje. Czy to trochę jak kanibalizm z SQL piszącym SQL? Pewny. Ale pozbyłoby się podzapytania i przyspieszyło UDF. Niech zacznie się dokuczanie.
Opcja 4 – Zapamiętaj to!
Chociaż SQL nie może bezpośrednio zapamiętywać, mamy SQL CLR. Przekonwertuj plik UDF na plik udf środowiska SQL CLR. W CLR możesz używać zmiennych statycznych. Możesz łatwo chwycić stół świąteczny w regularnych odstępach czasu i przechowywać je w tablicy mieszającej. Następnie po prostu przepisz swoją pętlę w CLR. Możesz nawet pójść dalej i zapamiętać całą odpowiedź, jeśli jest to właściwa logika.
Aktualizacja:
Opcja 1 - naprawdę starałem się skupić tutaj na ogólnych funkcjach, a nie na przykładowej funkcji, której użyłeś powyżej. Jednak obecny projekt twojego UDF pozwala na wielokrotne wywołanie stołu świątecznego, jeśli zdarzy ci się trafić kilka z rzędu. Użycie pewnego rodzaju tabeli w stylu kalendarza, która zawiera listę „złych dni” i odpowiadający im „następny dzień roboczy”, pozwoli wyeliminować możliwość wielu działań i zapytań.
Opcja 3 - Chociaż domena jest nieznana z wyprzedzeniem, możesz bardzo dobrze zmodyfikować swój świąteczny stół. Na dany dzień świąteczny będzie zawierał kolejny odpowiadający mu dzień roboczy. Na podstawie tych danych możesz wypluć UDF z długim opisem przypadku (kiedy „5/5/2012”, a następnie „5/14/2012” lub coś podobnego) na dole. Ta strategia może nie działać w przypadku każdego rodzaju problemu, ale może działać dobrze w przypadku niektórych rodzajów problemów.
Opcja 4 – Każda technologia ma konsekwencje. Należy wdrożyć środowisko CLR, zmodyfikować konfigurację SQL Server, a środowisko SQL CLR jest ograniczone do środowiska 3.5. Osobiście uważam, że te dostosowania są dość łatwe, ale twoja sytuacja może być inna (powiedzmy krnąbrny DBA lub ograniczenia dotyczące modyfikacji serwerów produkcyjnych).
Używanie zmiennych statycznych wymaga zestawów be przyznano PEŁNE ZAUFANIE . Musisz się upewnić, że Twoje blokowanie jest prawidłowe.
Istnieje pewne dowody że na bardzo wysoko poziomy transakcji CLR nie działa tak dobrze, jak bezpośredni SQL. Jednak w twoim scenariuszu ta obserwacja może nie mieć zastosowania, ponieważ nie ma bezpośredniej korelacji SQL dla tego, co próbujesz zrobić (zapamiętać).