sql >> Databasteknik >  >> RDS >> Sqlserver

Vad kan jag göra för att förbättra prestandan för min rena användardefinierade funktion i SQL Server?

Min första tanke här är -- vad är prestandaproblemet? Visst har du en loop (en gång per rad att tillämpa var) inom en loop som den kör en fråga. Men får du dåliga genomförandeplaner? Är dina resultatuppsättningar enorma? Men låt oss vända oss till det generiska. Hur löser man en gång detta problem? SQL gör egentligen inte memoisering (som den berömda @Martin_Smith påpekar). Så vad ska en pojke göra?

Alternativ 1 – Ny design

Skapa en helt ny design. I det här specifika fallet påpekar @Aaron_Bertrand att en kalendertabell kan uppfylla dina behov. Ganska rätt. Detta hjälper dig inte riktigt med situationer som inte är kalender, men som ofta är fallet i SQL måste du tänka lite annorlunda.

Alternativ 2 - Ring UDF-en mindre

Begränsa uppsättningen objekt som anropar denna funktion. Det här påminner mig mycket om hur man lyckas sökning/radräkning . Skapa en liten resultatuppsättning som har de distinkta värden som krävs och sedan ring din UDF så att den bara anropas ett fåtal gånger. Detta kan vara ett alternativ eller inte, men det kan fungera i många scenarier.

Alternativ 3 - Dynamisk UDF

Jag kommer förmodligen att bli utbuad ur rummet för det här förslaget, men här kommer. Det som gör denna UDF långsam är select-satsen inuti loopen. Om ditt julbord verkligen ändras sällan kan du sätta en trigger på bordet. Utlösaren skulle skriva ut och uppdatera UDF. Den nya UDF kan brutalt tvinga alla semesterbeslut. Skulle det lite som kannibalism med SQL som skriver SQL? Säker. Men det skulle bli av med underfrågan och påskynda UDF. Låt krånglet börja.

Alternativ 4 – Memoisera det!

Även om SQL inte kan memorera direkt, har vi SQL CLR. Konvertera UDF till en SQL CLR udf. I CLR får du använda statiska variabler. Du kan enkelt ta tag i Holidays-bordet med jämna mellanrum och lagra dem i en hashtabell. Sedan är det bara att skriva om din loop i CLR. Du kan till och med gå längre och memorera hela svaret om det är lämplig logik.

Uppdatering:

Alternativ 1 – Jag försökte verkligen fokusera på det allmänna här, inte på exempelfunktionen du använde ovan. Den nuvarande designen av din UDF tillåter dock flera anrop till julbordet om du råkar träffa några i rad. Genom att använda någon sorts kalenderliknande tabell som innehåller en lista över "dåliga dagar" och motsvarande "nästa arbetsdag" kan du ta bort risken för flera träffar och frågor.

Alternativ 3 - Även om domänen är okänd i förväg kan du mycket väl ändra ditt semesterbord. För en viss semesterdag skulle den innehålla nästa motsvarande arbetsdag. Från dessa data kan du spotta ut en UDF med en lång fallbeskrivning (när '5/5/2012' sedan '5/14/2012' eller något liknande) längst ner. Denna strategi kanske inte fungerar för alla typer av problem, men kan fungera bra för vissa typer av problem.

Alternativ 4 – Det finns konsekvenser för varje teknik. CLR måste distribueras, SQL Server-konfigurationen ändras och SQL CLR är begränsad till 3.5-ramverket. Personligen har jag tyckt att dessa justeringar är lätta nog, men din situation kan vara annorlunda (säg en motsträvig DBA, eller restriktioner för modifieringar av produktionsservrar).

Användning av statiska variabler kräver att sammansättningarna vara beviljas FULLSTÄNDIG FÖRTROENDE . Du måste se till att låsningen är korrekt.

Det finns vissa bevis det på mycket hög transaktionsnivåer CLR fungerar inte lika bra som direkt SQL. I ditt scenario kanske den här observationen inte är tillämplig eftersom det inte finns en direkt SQL-korrelation för vad du försöker göra (memoisera).



  1. classNotFound Undantag vid användning av JDBC för MYSQL på Tomcat i eclipse

  2. Använder XAMPP och Mysql Workbench tillsammans

  3. visar icke aggregerad kolumn i en grupp efter fråga i SQL

  4. PASS Summit 2013 :En succé i Charlotte