Introduktion
SQL Server-produktdokumentationen er lidt lys om emnet rækkemål . De vigtigste officielle referencer er i:
- Tip (Transact-SQL) – Forespørgsel (
FAST
ogDISABLE_OPTIMIZER_ROWGOAL
Tips) - DBCC TRACEON – Sporingsflag (Transact-SQL) (sporingsflag 4138)
- En forespørgsel kan tage lang tid at køre, hvis forespørgselsoptimeringsværktøjet bruger topoperatoren (KB 2667211)
Når folk beder om flere oplysninger, end der er indeholdt der, henviser jeg dem normalt til en eller flere af følgende:
- Rækkemål i aktion af SQL Server Query Optimization Team
- Rækkemål revideret – HURTIG vejledning også af SQL Server Query Optimization Team
- Row Goals Gone Rogue af Bart Duncan
- Inde i optimeringsværktøjet:Rækkemål i dybden af mig
- SSIS tuning tip, som alle savner af Rob Farley
For at opsummere kort:Rækkemålsfunktionen gør det muligt for optimizeren at generere en eksekveringsplan (eller dele af en eksekveringsplan) med det formål at returnere et bestemt antal rækker hurtigt. Dette er i modsætning til den normale adfærd (uden et rækkemål), som har til formål at finde en plan, der er optimeret til det komplette potentielle resultatsæt.
En rækkemålsstrategi betyder generelt at favorisere ikke-blokerende navigationsoperationer (f.eks. indlejrede loops joins, indekssøgninger og opslag) frem for blokerende, sæt-baserede operationer som sortering og hashing. Dette kan være nyttigt, når klienten kan drage fordel af en hurtig opstart og en konstant strøm af rækker (med måske en længere samlet eksekveringstid – se Rob Farleys indlæg ovenfor). Der er også de mere åbenlyse og traditionelle anvendelser f.eks. ved at præsentere resultater en side ad gangen.
Naturligvis er der et element af risiko forbundet med en rækkemålsplan. Hvis alt udspiller sig bredt, som optimeringsværktøjet forventer (ud fra de tilgængelige oplysninger og modelleringsantagelserne), vil udførelsesplanen begynde at streame det ønskede antal rækker hurtigere og mere effektivt, end det ville have været tilfældet uden rækkemålet.
Desværre, når rækkemålsstrategien går galt, kan det være en præstationskatastrofe (se Bart Duncans indlæg). Dette kan for eksempel ske, når optimeringsværktøjet har ufuldstændig information, støder på en ugunstig datafordeling eller gør en usikker antagelse. Under alle omstændigheder er årsagen til den dårlige ydeevne næsten altid, at der skal behandles mange flere rækker på udførelsestidspunktet, end optimeringsprogrammet forventede.
Det kan være meget nyttigt at identificere eksekveringsplanområder, der er påvirket af et rækkemål, fordi det hjælper os med at forstå hvorfor optimizeren traf de valg, den gjorde. Dette er især vigtigt, når rækkemålslogikken giver et negativt resultat. Uden at forstå hvilken rolle rækkemålet spiller, kan det se ud som om, at optimeringsværktøjet simpelthen undervurderede antallet af rækker, hvilket førte til, at folk leder de forkerte steder (f.eks. statistik) efter en grundlæggende årsag.
Indstilling af rækkemål
Det er meget nemmere at lede efter rækkemålseffekter, hvis man ved, hvilke slags ting der kan forårsage, at et rækkemål bliver sat i første omgang. Den officielle dokumentation taler ofte om, at rækkemål er forbundet med søgeordene TOP
, HURTIG
, IN
, og FINDER
. Dette kan efterlade læseren med en ufuldstændig eller vildledende forståelse, så det er værd at bruge et øjeblik på at afklare nogle aspekter.
Jeg vil lige på forhånd understrege, at brug af specifikke T-SQL-søgeord i en forespørgsel garanterer ikke, at der vil blive angivet et rækkemål . Den officielle dokumentation nævner visse søgeord for at hjælpe folk med at identificere almindelige scenarier, hvor rækkemål kan blive introduceret, uden at komme ind på alt for mange tekniske detaljer.
Et andet generelt punkt at huske på er, atet rækkemål kun indstilles, når målet ville være mindre end det almindelige estimat . Det nytter jo ikke så meget at generere et planfragment optimeret til 100 rækker, hvis det hele alligevel kun forventes at producere 50 rækker. For at være ekstra tydelig gælder dette punkt altid for alle de måder, et rækkemål kan sættes på. Hvis du forventer et rækkemål, men ikke kan se et, er dette en sandsynlig årsag.
Til sidst, for indledningen, bemærk, at rækkemål er en omkostningsbaseret optimeringsting; et rækkemål påvirker optimeringsvalg, så hvis der ikke er nogen valg, der skal træffes (dvs. en triviel plan), er der ingen rækkemålseffekt.
Lad os nu se på de ting, der kan sætte et rækkemål:
HURTIG og TOP
Brug af FAST
forespørgselstip er en pålidelig måde at angive et rækkemål ved roden af udførelsesplanen (med forbehold af de generelle undtagelser nævnt ovenfor). A SET ROWCOUNT n
sætning angiver også et lignende rækkemål på øverste niveau (når n
er selvfølgelig ikke nul) for de udsagn, det gælder for.
Skriver en TOP
klausul i en forespørgsel resulterer også meget ofte i et rækkemål. Så længe den færdige udførelsesplan indeholder en fysisk Top-operatør, er det sandsynligt, at mindst en del af planen under Top-operatøren var påvirket af et rækkemål (igen, de generelle vilkår og betingelser gælder).
Bemærk, at Topoperatorer introduceret af forespørgselsoptimeringsværktøjet (uden en forespørgselsspecificeret TOP
klausul) kan også angive et rækkemål. Dette er vigtigt, fordi der er alle mulige måder, hvorpå dette kan ske, for eksempel ved filtrering på et simpelt rækkenummer, som vist i følgende AdventureWorks-forespørgsel:
SELECT THN.RowNum, THN.TransactionID FROM ( SELECT TH.TransactionID, RowNum = ROW_NUMBER() OVER ( ORDER BY TH.TransactionID ASC) FROM Production.TransactionHistory AS TH WHERE TH.ProductID = 400 ) AS THN WHERE THN.RowNum >= 10 AND THN.RowNum < 20 ORDER BY THN.RowNum ASC;
Udførelsesplanen for den forespørgsel inkluderer en Top-operator tilføjet af optimeringsværktøjet (for at begrænse antallet af behandlede rækker til 20):