Forklar anslåede og faktiske forespørgselsplaner

Fuldført

Faktiske planer i forhold til estimerede udførelsesplaner kan være forvirrende. Forskellen er, at den faktiske plan indeholder kørselsstatistik, der ikke registreres i den anslåede plan. De anvendte operatorer og udførelsesrækkefølgen vil være den samme som den anslåede plan i næsten alle tilfælde. En anden overvejelse er, at registrering af en faktisk udførelsesplan kræver, at forespørgslen udføres, hvilket kan være tidskrævende eller ikke muligt. En UPDATE sætning kan f.eks. kun køres én gang. Men hvis du har brug for at se forespørgselsresultater og planen, skal du bruge en af de faktiske indstillinger for planen.

Skærmbillede af en estimeret udførelsesplan, der er genereret i SQL Server Management Studio.

Som vist kan du generere en anslået plan i SSMS ved at vælge den knap, der er angivet i feltet anslået forespørgselsplan (eller ved hjælp af tastaturkommandoen Control+L). Du kan generere den faktiske plan ved at vælge det viste ikon (eller ved hjælp af tastaturkommandoen Control+M) og derefter udføre forespørgslen. De to alternativknapper fungerer anderledes. Knappen Medtag anslået forespørgselsplan reagerer øjeblikkeligt på en hvilken som helst forespørgsel, der er fremhævet (eller hele arbejdsområdet, hvis intet er fremhævet), mens knappen Medtag faktisk forespørgselsplan kræver, at forespørgslen udføres.

Der er omkostninger ved både at udføre en forespørgsel og generere en anslået udførelsesplan, så visning af udførelsesplaner skal udføres omhyggeligt i et produktionsmiljø.

Du kan typisk bruge den anslåede udførelsesplan, mens du skriver din forespørgsel for at forstå dens ydeevneegenskaber, identificere manglende indekser eller registrere uregelmæssigheder i forespørgsler. Den faktiske udførelsesplan bruges bedst til at forstå forespørgslens kørselsydeevne og, hvad der er vigtigst, huller i statistiske data, der får forespørgselsoptimeringsprogrammet til at foretage uoptimelle valg baseret på de tilgængelige data.

Læs en forespørgselsplan

Udførelsesplaner viser dig, hvilke opgaver databaseprogrammet udfører, mens du henter de data, der er nødvendige for at opfylde en forespørgsel. Lad os se nærmere på planen.

SELECT [stockItemName]
 ,[UnitPrice] * [QuantityPerOuter] AS CostPerOuterBox
 ,[QuantityonHand]

FROM [Warehouse].[StockItems] s
 JOIN [Warehouse].[StockItemHoldings] sh ON s.StockItemID = sh.StockItemID
ORDER BY CostPerOuterBox;

Denne forespørgsel føjer tabellen StockItems til tabellen StockItemHoldings , hvor værdierne i kolonnen StockItemID er ens. Databaseprogrammet skal først identificere disse rækker, før det kan behandle resten af forespørgslen.

Skærmbillede af en plan for udførelse af forespørgsler.

Hvert ikon i planen repræsenterer en bestemt handling, som svarer til de forskellige handlinger og beslutninger, der udgør en udførelsesplan. SQL Server-databaseprogrammet har mere end 100 forespørgselsoperatorer, der kan være en del af en udførelsesplan. Under hvert operatorikon er der en omkostningsprocent i forhold til de samlede omkostninger for forespørgslen. Selv en handling, der viser en omkostning på 0% repræsenterer stadig nogle omkostninger. Faktisk skyldes 0% afrunding, da omkostninger til grafisk plan altid vises som hele tal, og den reelle procentdel er noget mindre end 0,5%.

Kørselsflowet i en udførelsesplan er fra højre mod venstre og oppefra og ned, så i denne plan er handlingen Clustered Index Scan på det StockItemHoldings.PK_Warehouse_StockItemHoldings grupperede indeks den første handling i forespørgslen. Bredden af de linjer, der forbinder operatorerne, er baseret på det anslåede antal rækker med data, der flyder videre til den næste operator. En tyk pil er en indikator for overførsel af store operatorer til operatorer og kan være et tegn på en mulighed for at finjustere en forespørgsel. Du kan også holde musen over en operator og se flere oplysninger i et værktøjstip.

Skærmbillede af et værktøjstip til handlingen Clustered Index Scan i tabellen StockItems.

Værktøjstippet fremhæver omkostningerne og estimaterne for den anslåede plan, og for en faktisk plan indeholder det sammenligninger af de faktiske rækker og omkostninger. Hver operator har også egenskaber, der indeholder flere oplysninger end værktøjstippet. Hvis du højreklikker på en bestemt operator, kan du vælge indstillingen Egenskaber i genvejsmenuen for at få vist hele egenskabslisten. Denne indstilling åbner en separat egenskabsrude i SQL Server Management Studio, som som standard er i højre side. Når ruden Egenskaber er åben, udfyldes listen Egenskaber med oplysninger om den pågældende operator, når du vælger en hvilken som helst operator. Du kan også åbne ruden Egenskaber ved at vælge Vis i den primære SQL Server Management Studio-menu og vælge Egenskaber.

Skærmbillede af egenskaberne for operatøren.

Ruden Egenskaber indeholder flere oplysninger og viser outputlisten med oplysninger om de kolonner, der overføres til den næste operator. Disse kolonner kan indikere, at der er behov for et indeks, der ikke er med i klyngen, for at forbedre forespørgslens ydeevne, når de analyseres med en grupperet indeksscanning. Da en scanningshandling for et grupperet indeks læser hele tabellen, kan et ikke-grupperet indeks i kolonnen StockItemID i hver tabel være mere effektivt i dette scenarie.

Letvægtsforespørgselsprofilering

Når du genererer faktiske udførelsesplaner, uanset om du bruger SSMS eller den udvidede hændelsesovervågningsinfrastruktur, kan det medføre betydelige omkostninger. Derfor er denne proces typisk reserveret til fejlfinding af livewebsteder. Observatør-overhead, som det er kendt, er omkostningerne ved at overvåge et kørende program. I nogle scenarier kan denne omkostning kun være nogle få procentpoint af CPU-udnyttelsen, men i andre tilfælde kan det, f.eks. registrere faktiske udførelsesplaner, reducere ydeevnen for individuelle forespørgsler betydeligt. Den ældre profilering i SQL Server-programmet kan medføre op til 75% omkostninger til hentning af forespørgselsoplysninger, mens den lette profilering har en maksimal belastning på ca. 2%.

I den første version af letvægtsprofilering indsamlede den oplysninger om rækkeantal og I/O-udnyttelse (antallet af logiske og fysiske læsninger og skrivninger udført af databaseprogrammet for at opfylde en given forespørgsel). Derudover blev der introduceret en ny udvidet hændelse kaldet query_thread_profile for at gøre det muligt at inspicere data fra hver operator i en forespørgselsplan. I den indledende version af letvægtsprofilering kræver brugen af funktionen, at sporingsflag 7412 er aktiveret globalt.

Hvis letvægtsprofilering ikke er aktiveret globalt, kan du bruge USE HINT forespørgselstip til QUERY_PLAN_PROFILE til at aktivere letvægtsprofilering på forespørgselsniveau. Når en forespørgsel med dette tip fuldfører udførelsen, genereres der en query_plan_profile udvidet hændelse, hvilket giver en faktisk udførelsesplan. Her er et eksempel på en forespørgsel med dette tip:

SELECT [stockItemName]
 ,[UnitPrice] * [QuantityPerOuter] AS CostPerOuterBox
 ,[ QuantityonHand]
FROM [Warehouse].[StockItems] s
    JOIN [Warehouse].[StockItems] sh ON s.StockItemID = sh.StockItemID
ORDER BY CostPerOuterBox 
OPTION(USE HINT ('QUERY_PLAN_PROFILE'));

Statistik for seneste forespørgselsplaner

Letvægtsprofilering er som standard aktiveret i både SQL Server 2019 og Azure SQL Database og administreret instans. Letvægtsprofilering er også tilgængelig som en konfigurationsmulighed med databaseomfang, kaldet LIGHTWEIGHT_QUERY_PROFILING. Med indstillingen databaseområde kan du deaktivere funktionen for alle dine brugerdatabaser uafhængigt af hinanden.

Der er også en dynamisk administrationsfunktion kaldet sys.dm_exec_query_plan_stats, som kan vise dig den sidst kendte faktiske plan for udførelse af forespørgsler for en given planhandle. Hvis du vil se den sidst kendte faktiske forespørgselsplan via funktionen, kan du aktivere sporingsflag 2451 på serveren. Du kan også aktivere denne funktionalitet ved hjælp af en konfigurationsindstilling med databaseomfang, der hedder LAST_QUERY_PLAN_STATS.

Du kan kombinere denne funktion med andre objekter for at få den sidste udførelsesplan for alle cachelagrede forespørgsler:

SELECT *
FROM sys.dm_exec_cached_plans AS cp
    CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
    CROSS APPLY sys.dm_exec_query_plan_stats(plan_handle) AS qps; 
GO

Med denne funktionalitet kan du hurtigt identificere kørselsstatistikken for den sidste udførelse af en forespørgsel i dit system med minimale omkostninger. På følgende billede kan du se, hvordan du henter planen. Hvis du vælger XML-udførelsesplanen, som er den første kolonne med resultater, vises den udførelsesplan, der vises på det andet billede nedenfor.

Skærmbillede af hentning af den faktiske udførelsesplan for en forespørgsel.

Som du kan se fra egenskaberne for Columnstore Index Scan på følgende billede, har den plan, der er hentet fra cachen, det faktiske antal rækker, der er hentet i forespørgslen.

Skærmbillede af den hentede udførelsesplan, der viser, at cachen har det faktiske antal rækker, der er hentet i forespørgslen.