En av de tuffaste utmaningarna i SQL Server är att felsöka problem med parameterkänslighet eller kardinalitetsuppskattning som orsakar prestandaförsämring av en arbetsbelastning. I allmänhet måste du ha den faktiska exekveringsplanen från uttalandet igång för att kunna fastställa orsaken till prestandaförsämringen. I SQL Server 2012 ger query_post_execution_showplan Extended Event möjligheten att fånga den faktiska exekveringsplanen för satser. Men hur användbart detta än verkar, är denna händelse inte något som kan användas utan en betydande prestandapåverkan på arbetsbelastningen som körs på servern.
I min artikel Mätning av "Observer Overhead" av SQL Trace vs. Extended Events visade jag en jämförelse av prestandapåverkan av SQL Trace mot en identisk konfiguration med Extended Events i SQL Server 2012. Vid den tidpunkten gjorde jag ursprungligen testet för den artikeln Jag testade också en hel del av händelsen query_post_execution_showplan i SQL Server 2012. Den här händelsen introducerades först i SQL Server 2012 CTP1 när många av spårningshändelserna överfördes till Extended Events för att ge paritet med SQL Trace. Vid den tiden hade händelsen bara en delmängd av kolumnerna som inkluderades i den slutliga RTM för SQL Server 2012.
Under CTP1 skickade jag ett Connect-objekt som begärde att en åtgärd skulle skapas för att möjliggöra insamling av den faktiska exekveringsplanen med händelser i SQL Server 2012. Målet var att kunna använda händelserna module_end eller sql_statement_completed för att identifiera när en procedur körs eller uttalandet överskrider sin normala varaktighet. Till exempel, i scenariot med parameterkänslighet, där en mindre idealisk plan genereras för de normala parametervärdena, kan händelsen användas för att samla in den faktiska exekveringsplanen för den satsen genom en åtgärd. Som svar lade SQL Server-teamet till kolumnerna duration och cpu_time till händelsen query_post_execution_showplan för att möjliggöra för predikatdefinitioner att endast samla in denna händelse för dessa scenarier.
Tyvärr har detta inte samma fördelar som en implementering som en åtgärd skulle ha haft på prestanda. I resten av det här inlägget ska jag förklara varför.
Prestandapåverkan
Vid den tidpunkt då jag testade min tidigare artikel testade jag också overheaden i samband med händelsen query_post_execution_showplan, främst för att jag verkligen var intresserad av att använda den i ett par kundproduktionssystem och innan jag gjorde det behövde jag förstå vad vilken typ av inverkan händelsen skulle ha på deras arbetsbelastning. Jag blev verkligen bestört över resultaten jag fick från mina ursprungliga tester, och efter att ha låtit Aaron Bertrand validera mina resultat med SQL Sentrys interna testsele, lämnade jag in ett annat Connect-objekt som rapporterade prestandaproblemen som sedan har stängts som "By Design" .
För att testa prestandapåverkan användes exakt samma arbetsbelastning och Distributed Replay-konfiguration från artikeln Mätning av "Observer Overhead" av SQL Trace vs. Extended Events. Den enda skillnaden för testresultaten som visas i den här artikeln är att ett nyare, kraftfullare värdsystem användes för VM-miljön. De virtuella datorerna som användes var exakt likadana, utan ändringar i deras konfiguration, och de kopierades helt enkelt till det nya systemet, vilket är anledningen till att baslinjearbetsbelastningen kunde utföra omspelningen snabbare med ett högre genomsnittligt antal batchbegäranden/sek. Baslinjeresultaten fångades in med en standardinstallation av SQL Server 2012 med endast standardsessionen system_health som kördes på servern.
För jämförelse av prestandapåverkan av query_post_execution_showplan
händelse användes följande definition av händelsesession.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan( WHERE ([duration]=(5000000))); GO
Denna session samlar faktiskt inte in händelsedata med hjälp av ett mål och använder ett predikat på varaktigheten för händelsens varaktighet är lika med 5000000 mikrosekunder, eller fem sekunders varaktighet. För replay-arbetsbelastningen har ingen exekvering av uttalanden en varaktighet på exakt fem sekunder, så händelsen query_post_execution_showplan utlöses faktiskt aldrig på servern, och eventuell prestandaförsämring är enbart resultatet av händelsedatainsamlingen och sedan predikatutvärderingen. Resultaten från testerna visas i tabell 1 och i diagram 2.
Tabell 1 – query_post_execution händelseoverhead
Diagram 2 – query_post_execution event overhead
För den här testomgången försämras arbetsbelastningens prestanda med ungefär 30 % genom att helt enkelt ha denna händelse aktiverad i en händelsesession, även om den inte aktiveras för någon av händelserna som spelas om på servern. Den övergripande försämringen kommer att bero på den faktiska arbetsbelastningen för servern, och det är viktigt att notera att denna serie av tester återspeglar mer av ett värsta scenario eftersom Distributed Replay kördes i stressläge och CPU-användningen på SQL Server var kopplad på 94 % i genomsnitt under testerna.
Förstå prestandapåverkan
Anledningen till att den här händelsen innebär en så betydande omkostnad på prestanda kan förklaras från händelsens livscykel i Extended Events. När en kritisk punkt i SQL Server-koden associerad med en händelse påträffas under exekvering, utför koden en mycket snabb boolesk kontroll för att avgöra om händelsen är aktiverad i någon aktiv händelsesession på servern. Om händelsen är aktiverad för en aktiv händelsesession, samlas alla datakolumner som är associerade med händelsen, inklusive eventuella anpassningsbara kolumner som har aktiverats. Vid denna tidpunkt utvärderar händelsen eventuella predikat för de aktiva händelsesessionerna som samlar in händelsen för att avgöra om händelsen faktiskt kommer att starta helt.
För händelsen query_post_exection_showplan kommer all prestandapåverkan från de omkostnader som är kopplade till datainsamlingen. Även i fallet där det finns ett predikat för en varaktighet som är lika med fem sekunder, bara genom att aktivera händelsen i en händelsesession, måste den samla in Showplan XML för varje sats som körs på servern bara för att kunna utvärdera predikatet och bestäm sedan att händelsen inte kommer att starta. Av denna anledning bör händelsen query_post_execution_showplan undvikas för produktionsbelastningar. För arbetsbelastningen för testrepriset behövde händelsen utvärderas ungefär 440 000 gånger, även om den faktiskt inte startar för arbetsbelastningen och händelsesessionen som testas eftersom ingen av reprishändelserna har en varaktighet på exakt fem sekunder. Händelseräkningsinformationen samlades in genom att lägga till event_counter-målet till händelsesessionen och ta bort varaktighetspredikatet och sedan testa omuppspelningsarbetsbelastningen med följande sessionsdefinition.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan ADD TARGET package0.event_counter; GO
Jämförelse med snabbavfyrande händelser
För att ge en referensram för denna prestandapåverkan kan vi titta på kostnaden för att slå på en uppsättning ofta körande händelser på servern och utföra samma omspelningsarbetsbelastning. Två av de vanligast körda händelserna i SQL Server är händelserna lock_acquired och lock_released. För att jämföra overheaden för dessa två händelser kan följande händelsesession användas, som samlar händelserna utan predikat så att varje avrättning samlas in och räknar hur ofta de skjuter med målet event_counter.
CREATE EVENT SESSION [locking Overhead] ON SERVER ADD EVENT sqlserver.lock_acquired, ADD EVENT sqlserver.lock_released ADD TARGET package0.event_counter; GO
För vår repris-arbetsbelastning avfyras dessa två händelser ungefär 111 180 000 gånger. Omkostnaderna för att samla in dessa händelser kan ses i tabell 3 och diagram 4.
Tabell 3 – Jämförelse av låsningskostnader
Diagram 4 – Jämförelse av låshändelser
Som du kan se från data är prestandaeffekten av dessa händelser betydligt lägre än för query_post_execution_showplan, även om definitionen av låshändelssessionen konfigurerades för att tillåta alla händelser att aktiveras på servern, var den totala overheaden under 1 % totalt sett . Tänk på att den låsande händelsesessionen utvärderade motsvarande 500 gånger fler händelser, och i det här fallet var alla händelser faktiskt tvungna att aktiveras för händelsesessionen, där händelsen query_post_execution_showplan faktiskt inte behövde aktiveras efter att ha utvärderats.
Sammanfattning
Medan query_post_execution_showplan-händelsen ger möjlighet att samla in den faktiska frågeplanen för en sats som körs, gör resultateffekten av datainsamlingen bara för att utvärdera händelsen det till något som inte är lönsamt för produktionsanvändning. Åtminstone bör omkostnader övervägas innan du någonsin använder denna händelse mot en produktionsbelastning. Till och med händelsebeskrivningen som tillhandahålls av Microsoft erkänner att händelsen kan ha en betydande inverkan på prestanda (min markering):
Uppstår efter att en SQL-sats exekveras. Denna händelse returnerar en XML-representation av den faktiska frågeplanen. Att använda den här händelsen kan medföra betydande prestandakostnader, så den bör endast användas vid felsökning eller övervakning av specifika problem under korta tidsperioder.Händelsebeskrivningen finns i beskrivningskolumnen i katalogvyn sys.dm_xe_objects eller i gränssnittet för nya sessioner som visas i figur 5 (min markering):
Figur 5 – Händelsebeskrivning från gränssnittet för den nya sessionen
Jag skulle rekommendera att jämföra prestandan för alla händelser med denna varning i beskrivningen innan du faktiskt använder den i en produktionsmiljö.