Execution Plans - Uge 9

28. maj 2021
I dag skriver jeg om Exectution Plans i SQL Server. Execution Plans er det vigtigste værktøj for at forstå og arbejde med Performange Tuning på SQL Serveren, og for at kunne lave effektive ændringer i queries. Så i dag starter jeg ud med en introduktion til Execution Plans og hvordan man kan fortolke og læse dem.
Brian Bønk Rueløkke
PRINCIPAL ARCHITECT
Uge 9 - Execution Plans

Hvorfor Execution Plans?

Mange har spurgt mig hvorfor der overhovedet er Execution Plans i SQL serveren. Eks. “Vi har en query og hvorfor eksekverer SQL serveren ikke selv denne?”

For at svare på de spørgsmål, bliver jeg nødt til at starte med en lidt tætte gennemgang af SQL som kodesprog (og ja, nogen vil mene det ikke er et kodesprog, men den snak kan vi tage en anden dag 😀). SQL sproget (og også T-SQL på SQL serveren) er et declarative language (deklarativt sprog). Man beskriver logisk hvilken data man skal bruge fra databasen (SELECT) eller hvilken data der skal ændres (UPDATE, INSERT, DELETE). Et eksempel på nedenstående query:

Med denne query fortæller man databasen og den underliggende engine (se uge 1) at:

  • Jeg vil gerne have al data fra tabel a og b
  • Begge tabeller skal sættes sammen via id-kolonnen
  • Rækkerne fra tabel a skal filtreres på ‘field’ ud fra ‘EnVærdi’

Vi beskriver kun, gennem SQL kode, hvordan resultatet af det data som querien henter skal se ud. Med en SQL query, kan du kun specificere resultatet – ikke andet. Man kan ikke fortælle SQL serveren hvordan den skal tilgå data fysisk/logisk og hvordan den ellers skal eksekvere og behandle det data, der skal arbejdes med.

Man tilgår med andre ord altid data på SQL serveren via et logisk lag, beskrivende hvilke elementer af data, der skal anvendes eller ændres. Men SQL serveren skal bruge en fysisk execution plan som i steps beskriver hvordan data skal hentes eller ændres. Execution Plan er en form for strategi udvalgt og planlagt af Query Optimizeren til at hente og behandle data.

En analogi: Forestil dig at fuldføre en rejse mellem to byer – fra Kolding til Odense, så har du bestemt dig for det logiske udtryk. Dette logiske udtryk, kan have mange forskellige fysiske fortolkninger:

  • Man kan gå
  • Køre på cykel
  • Tage toget/bilen/rulleskøjter

Det er underordnet hvilken fortolkning man anvender her, uanset hvilken der vælges er der igen flere forskellige fortolktninger af den del. Mulighederne eksploderer. Opgaven er at finde den mulighed som koster mindst og samtidig kræver mindst energi.

Vi vil som mennesker nok vælge bilen, men den koster jo mere end at gå.

Det samme problem har Query Optimizeren i SQL serveren. Query Optimizeren skal vælge den Execution Plan som kræver mindst arbejde, men som stadig tilgodeser kravene fra querien. Udfordringen for Query Optimizeren er at finde en Execution Plan der er god nok fra det overordnede Search Space – og dette Search Space kan være ret så stort hvis der er mange tabeller og indexes i den specifikke query.

 

Hvordan man læser en Execution Plan

Første gang man overhovedet kigger på en Execution Plan kan man godt blive blæst bagover og synes de er underlige. Det kan være svært ved første øjekast at forstå og fortolke dem korrekt. Et eks:

Som du kan se af ovenstående, så indeholder alle Execution Plans flere trin, også kaldet Operators på SQL serveren. Disse operators er row-by-row fra SQL serveren, hvilket betyder at rækker fra data flyder fra højre mod venstre i Execution Plan.

I ovenstående tilfælde starter SQL serveren med at ekekvere det første trin Index Seek (NonClustered) operator på tabellen CustomerAddress. Hver enkelt række fra dette skan løber videre til Nested Loop operator, som kommer efter et scan. Og for hver række heri, foretager SQL serveren en Key Lookup (Clustered) operator (Bookmark Lookup, måske du kan huske den) på den samme tabel. Hvis der er en række der matcher, bliver denne række sendt videre til SELECT operator, som er den der endeligt returnerer resultatet tilbage til brugeren.

Som du måske allerede nu kan se, er det lettere at læse en Execution Plan fra højre mod venstre, fordi det er også denne vej rækker med data flyder. En Execution Plan er stadig fysisk eksekveret fra venstre mod højre. Vi læser den blot fra højre mod venstre for at følge data.

Jeg håber denne tilgang giver dig lige mere blod på tanden til at forsøge at forstå og læse Execution Plans. Hvis du vil mere i dybden med operators kan du læse mere om dem her:

Opsummering – Execution Plans

Jeg har skrevet lidt om og introduceret Execution Plans til dig i denne udgave af SQL Performance Tuning, og hvordan de kan blive læst og fortolktet. Vi kommukerer altid med SQL serveren via et logisk lag; vi beskriver det data vil skal bruge eller vil ændre.

Query Optimizeren har til opgave at bygge en god nok Execution Plan til disse queries. Og Execution Plan er den der slutteligt beskriver de fysiske trin der skal udføres på SQL serveren for at tilgodese queries. I næste uge kommer der mere om Execution Plans og Plan Caching – og hvorfor det kan være både godt og skidt.

Har du misset nogle af de tidligere indlæg, kan du finde dem herunder:

Data & AI

Fra enkle datavisualiseringer til mere komplekse Business Intelligence og Data Warehouse løsninger.

Data & AI
Læs mere om vores Data & AI løsninger
Data & AI