Mijn eerste gedachte hier is - wat is het prestatieprobleem? Natuurlijk heb je een lus (eenmaal per rij om waar toe te passen) binnen een lus die een query uitvoert. Maar krijgt u slechte uitvoeringsplannen? Zijn je resultatensets enorm? Maar laten we ons wenden tot het generieke. Hoe lost dit probleem ooit op? SQL doet niet echt aan memorisatie (zoals de illustere @Martin_Smith aangeeft). Dus wat moet een jongen doen?
Optie 1 - Nieuw ontwerp
Maak een geheel nieuw ontwerp. In dit specifieke geval wijst @Aaron_Bertrand erop dat een kalendertafel aan uw behoeften kan voldoen. Juist. Dit helpt je niet echt bij niet-kalendersituaties, maar zoals vaak het geval is in SQL moet je een beetje anders denken.
Optie 2 - Bel de UDF Less
Beperk de set items die deze functie aanroepen. Dit doet me veel denken aan hoe ik succesvolle paging/rijtelling . Genereer een kleine resultatenset met de vereiste afzonderlijke waarden en dan bel je UDF, zodat deze maar een paar keer wordt aangeroepen. Dit kan al dan niet een optie zijn, maar kan in veel scenario's werken.
Optie 3 - Dynamische UDF
Ik zal waarschijnlijk uit de kamer worden uitgejouwd voor deze suggestie, maar hier gaat het. Wat deze UDF traag maakt, is de select-instructie in de lus. Als uw vakantietafel echt niet vaak verandert, kunt u een trigger op de tafel leggen. De trigger zou UDF wegschrijven en bijwerken. De nieuwe UDF zou alle vakantiebeslissingen bruut kunnen forceren. Zou het een beetje lijken op kannibalisme met SQL die SQL schrijft? Zeker. Maar het zou de subquery verwijderen en de UDF versnellen. Laat het gekibbel beginnen.
Optie 4 - Onthoud het!
Hoewel SQL niet direct kan onthouden, hebben we wel SQL CLR. Converteer de UDF naar een SQL CLR udf. In CLR mag je statische variabelen gebruiken. Je zou de Holidays-tabel gemakkelijk op een bepaald moment kunnen pakken en opslaan in een hashtabel. Herschrijf dan gewoon je lus in de CLR. Je zou zelfs verder kunnen gaan en het hele antwoord uit je hoofd kunnen leren als dat logisch is.
Bijwerken:
Optie 1 - Ik probeerde me hier echt op het algemene te concentreren, niet op de voorbeeldfunctie die je hierboven hebt gebruikt. Het huidige ontwerp van uw UDF maakt echter meerdere oproepen naar de Holiday-tabel mogelijk als u er een paar op een rij raakt. Door een soort kalender-stijltabel te gebruiken die een lijst met 'slechte dagen' en de bijbehorende 'volgende werkdag' bevat, kunt u de kans op meerdere hits en zoekopdrachten verwijderen.
Optie 3 - Hoewel het domein van tevoren onbekend is, kunt u uw vakantietabel heel goed wijzigen. Voor een bepaalde vakantiedag zou het de volgende overeenkomstige werkdag bevatten. Uit deze gegevens zou je een UDF kunnen uitspugen met een lange case-statement (wanneer '5/5/2012' dan '5/14/2012' of iets dergelijks) onderaan. Deze strategie werkt misschien niet voor elk type probleem, maar zou goed kunnen werken voor sommige soorten problemen.
Optie 4 - Elke technologie heeft gevolgen. CLR moet worden geïmplementeerd, de SQL Server-configuratie moet worden aangepast en SQL CLR is beperkt tot het 3.5-framework. Persoonlijk vond ik deze aanpassingen eenvoudig genoeg, maar jouw situatie kan anders zijn (bijvoorbeeld een weerbarstige DBA, of beperkingen op aanpassingen aan productieservers).
Het gebruik van statische variabelen vereist de assemblages be VOLLEDIG VERTROUWEN verleend . Je moet ervoor zorgen dat je vergrendeling correct is.
Er is enig bewijs dat op zeer hoog transactieniveaus CLR presteert niet zo goed als directe SQL. In uw scenario is deze observatie echter mogelijk niet van toepassing omdat er geen directe SQL-correlatie is voor wat u probeert te doen (memoriseren).