sql >> Database teknologi >  >> RDS >> Sqlserver

Hvad kan jeg gøre for at forbedre ydeevnen af ​​min rene brugerdefinerede funktion i SQL Server?

Min første tanke her er -- hvad er ydelsesproblemet? Sikker på, at du har en løkke (en gang pr. række til at anvende hvor) i en løkke, at den kører en forespørgsel. Men får du dårlige udførelsesplaner? Er dine resultatsæt enorme? Men lad os vende os til det generiske. Hvordan løser man en gang dette problem? SQL laver ikke rigtig memoisering (som den berømte @Martin_Smith påpeger). Så hvad skal en dreng gøre?

Mulighed 1 - Nyt design

Skab et helt nyt design. I dette specifikke tilfælde påpeger @Aaron_Bertrand, at en kalendertabel kan opfylde dine behov. Helt rigtigt. Dette hjælper dig ikke rigtigt med situationer uden for kalenderen, men som det ofte er tilfældet i SQL, skal du tænke lidt anderledes.

Mulighed 2 - Kald UDF'en mindre

Indsnævre det sæt af elementer, der kalder denne funktion. Dette minder mig meget om, hvordan man gør optælling af sidesøgning/række . Generer et lille resultatsæt, der har de distinkte værdier, der kræves og derefter ring til din UDF, så den kun bliver kaldt et par gange. Dette er muligvis en mulighed, men det kan fungere i mange scenarier.

Mulighed 3 - Dynamisk UDF

Jeg bliver sikkert buhret ud af lokalet for dette forslag, men her kommer. Det, der gør denne UDF langsom, er select-sætningen inde i løkken. Hvis dit julebord virkelig ændrer sig sjældent, kan du sætte en udløser på bordet. Udløseren ville skrive ud og opdatere UDF. Den nye UDF kunne brute force alle ferie beslutninger. Ville det lidt ligesom kannibalisme med SQL, der skriver SQL? Jo da. Men det ville slippe af med underforespørgslen og fremskynde UDF'en. Lad skænderiet begynde.

Mulighed 4 - Husk det!

Selvom SQL ikke direkte kan huske, har vi SQL CLR. Konverter UDF til en SQL CLR udf. I CLR kommer du til at bruge statiske variable. Du kan nemt få fat i Holidays-bordet med et jævnt mellemrum og gemme dem i en hashtabel. Så skal du bare omskrive din loop i CLR. Du kan endda gå videre og huske hele svaret, hvis det er passende logik.

Opdatering:

Mulighed 1 - Jeg prøvede virkelig at fokusere på det generelle her, ikke den eksempelfunktion, du brugte ovenfor. Det nuværende design af din UDF giver dog mulighed for flere opkald til feriebordet, hvis du tilfældigvis rammer et par stykker i træk. Ved at bruge en slags kalender-stil-tabel, der indeholder en liste over 'dårlige dage' og den tilsvarende 'næste arbejdsdag', vil du kunne fjerne potentialet for flere hits og forespørgsler.

Mulighed 3 - Selvom domænet er ukendt i forvejen, kan du meget vel ændre dit feriebord. For en given feriedag vil den indeholde den næste tilsvarende arbejdsdag. Fra disse data kan du spytte en UDF ud med en lang sagserklæring (når '5/5/2012' derefter '5/14/2012' eller noget lignende) nederst. Denne strategi virker muligvis ikke for alle typer problemer, men kan fungere godt for nogle typer problemer.

Mulighed 4 - Der er konsekvenser for enhver teknologi. CLR skal implementeres, SQL Server-konfigurationen skal ændres, og SQL CLR er begrænset til 3.5 frameworket. Personligt har jeg fundet disse justeringer nemme nok, men din situation kan være anderledes (f.eks. en genstridig DBA eller begrænsninger for ændringer af produktionsservere).

Brug af statiske variabler kræver, at samlingerne er tildelt FULD TILLID . Du skal sørge for at få din låsning korrekt.

Der er nogle beviser det på meget højt transaktionsniveauer CLR fungerer ikke så godt som direkte SQL. I dit scenarie er denne observation muligvis ikke anvendelig, fordi der ikke er en direkte SQL-sammenhæng for, hvad du forsøger at gøre (memoize).



  1. SQL-forespørgsel for at hente data fra to tabeller, der ikke er i stand

  2. ora-06553 pls-306 forkert antal eller typer af argumenter i kald til 'ogc_x'

  3. Oracle-konverterer SQL til ANSI SQL

  4. Kan ReadUncommitted kende alle LAVERE auto-increment ID'er, der vil eksistere?