sql >> Databasteknik >  >> RDS >> Database

Observer Overhead- och väntetypssymptom

Många människor använder väntestatistik som en del av deras övergripande felsökningsmetod för prestanda, liksom jag, så frågan jag ville utforska i det här inlägget handlar om väntetyper förknippade med observatörskostnader. Med observatörskostnader menar jag påverkan på SQL Server-arbetsbelastning som orsakas av SQL Profiler, spårningar på serversidan eller utökade händelsesessioner. För mer om ämnet observer overhead, se följande två inlägg från min kollega Jonathan Kehayias :

  • Mätning av "Observer Overhead" av SQL Trace vs. Extended Events
  • Effekten av query_post_execution_showplan Extended Event i SQL Server 2012

Så i det här inlägget skulle jag vilja gå igenom några varianter av observatörsoverhead och se om vi kan hitta konsekventa väntetyper förknippade med den uppmätta nedbrytningen. Det finns en mängd olika sätt som SQL Server-användare implementerar spårning i sina produktionsmiljöer, så dina resultat kan variera, men jag ville täcka några breda kategorier och rapportera tillbaka om vad jag hittade:

  • Användning av SQL Profiler-session
  • Spåranvändning på serversidan
  • Spåra användning på serversidan, skriva till en långsam I/O-väg
  • Utökad händelseanvändning med ett ringbuffertmål
  • Utökad användning av händelser med ett filmål
  • Utökad händelseanvändning med ett filmål på en långsam I/O-sökväg
  • Utökad händelseanvändning med ett filmål på en långsam I/O-sökväg utan händelseförlust

Du kan antagligen komma på andra varianter av temat och jag inbjuder dig att dela med dig av alla intressanta rön om observatörsoverhead och väntestatistik som en kommentar i det här inlägget.

Baslinje

För testet använde jag en virtuell VMware-maskin med fyra vCPU:er och 4 GB RAM. Min virtuella maskingäst var på OCZ Vertex SSD:er. Operativsystemet var Windows Server 2008 R2 Enterprise och versionen av SQL Server är 2012, SP1 CU4.

När det gäller "arbetsbelastningen" använder jag en skrivskyddad fråga i en loop mot 2008 års kreditprovsdatabas, inställd på GO 10 000 000 gånger.

USE [Credit];
GO
 
SELECT TOP 1 
     [member].[member_no],
     [member].[lastname],
     [payment].[payment_no],
     [payment].[payment_dt],
     [payment].[payment_amt]
FROM [dbo].[payment]
INNER JOIN [dbo].[member]
ON [member].[member_no] = [payment].[member_no];
GO 10000000

Jag kör också den här frågan via 16 samtidiga sessioner. Slutresultatet på mitt testsystem är 100 % CPU-användning över alla vCPU:er på den virtuella gästen och i genomsnitt 14 492 batchförfrågningar per sekund under en period på två minuter.

När det gäller händelsespårningen använde jag i varje test Showplan XML Statistics Profile för spårningstesterna SQL Profiler och Server-side – och query_post_execution_showplan för utökade evenemangssessioner. Exekutivplanshändelser är mycket dyra, det är just därför jag valde dem så att jag kunde se om jag under extrema omständigheter kunde härleda teman av väntetyp eller inte.

För att testa ackumulering av väntetyp under en testperiod använde jag följande fråga. Inget märkvärdigt – bara att rensa statistiken, vänta 2 minuter och sedan samla de 10 bästa vänteackumuleringarna för SQL Server-instansen under nedbrytningstestperioden:

-- Clearing the wait stats
 
DBCC SQLPERF('waitstats', clear);
 
WAITFOR DELAY '00:02:00';
GO
 
SELECT TOP 10
     [wait_type],
     [waiting_tasks_count],
     [wait_time_ms]
FROM sys.[dm_os_wait_stats] AS [ws]
ORDER BY [wait_time_ms] DESC;

Observera att jag inte är det filtrera bort bakgrundsväntetyper som vanligtvis filtreras bort, och det beror på att jag inte ville eliminera något som normalt är godartat – men i den här omständigheten faktiskt pekar på ett verkligt område att undersöka vidare.

SQL Profiler Session

Följande tabell visar före- och efter-batchförfrågningar per sekund när du aktiverar en lokal SQL Profiler-spårningsspårning Showplan XML Statistics Profile (kör på samma virtuella dator som SQL Server-instansen):

Baslinjebatchbegäranden per sekund
(2 minuter i genomsnitt)
SQL Profiler Session Batch Requests per Second
(2 minuter i genomsnitt)
14 492 1 416

Du kan se att spårningen av SQL Profiler orsakar en betydande minskning av genomströmningen.

När det gäller ackumulerad väntetid under samma period var de bästa väntetyperna följande (som med resten av testerna i den här artikeln gjorde jag några testkörningar och resultatet var generellt konsekvent):

wait_type waiting_tasks_count väntetid_ms
TRACEWRITE 67 142 1 149 824
FT_IFTS_SCHEDULER_IDLE_WAIT 4 237 003
SLEEP_TASK 313 180 449
REQUEST_FOR_DEADLOCK_SEARCH 24 120 111
HADR_FILESTREAM_IOMGR_IOCOMPLETION 240 120 086
LAZYWRITER_SLEEP 120 120 059
DIRTY_PAGE_POLL 1 198 120 038
HADR_WORK_QUEUE 12 120 015
LOGMGR_QUEUE 937 120 011
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 006

Väntetypen som hoppar ut för mig är TRACEWRITE – som definieras av Books Online som en väntetyp som "uppstår när spårningsleverantören för SQL Trace-raduppsättning väntar på antingen en ledig buffert eller en buffert med händelser att bearbeta". Resten av väntetyperna ser ut som vanliga väntetyper i bakgrunden som man vanligtvis skulle filtrera bort från din resultatuppsättning. Dessutom pratade jag om ett liknande problem med överspårning i en artikel 2011 som heter Observer overhead – farorna med för mycket spårning – så jag kände till den här väntetypen ibland korrekt pekar på observatörs overhead-problem. Nu i just det fallet jag bloggade om var det inte SQL Profiler, utan en annan applikation som använder rowset-spårningsleverantören (ineffektivt).

Spårning på serversidan

Det var för SQL Profiler, men hur är det med spårning på serversidan? Följande tabell visar före- och efter-batchbegäranden per sekund när du aktiverar en lokal server-side-spårskrivning till en fil:

Baslinjebatchbegäranden per sekund
(2 minuter i genomsnitt)
SQL Profiler Batch Requests per Second
(2 minuter i genomsnitt)
14 492 4 015

De bästa väntetyperna var följande (jag gjorde några testkörningar och resultatet var konsekvent):

wait_type waiting_tasks_count väntetid_ms
FT_IFTS_SCHEDULER_IDLE_WAIT 4 237 015
SLEEP_TASK 253 180 871
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 046
HADR_WORK_QUEUE 12 120 042
REQUEST_FOR_DEADLOCK_SEARCH 24 120 021
XE_DISPATCHER_WAIT 3 120 006
VÄNTA 1 120 000
LOGMGR_QUEUE 931 119 993
DIRTY_PAGE_POLL 1 193 119 958
XE_TIMER_EVENT 55 119 954

Den här gången ser vi inte TRACEWRITE (vi använder en filleverantör nu) och den andra spårningsrelaterade väntetypen, den odokumenterade SQLTRACE_INCREMENTAL_FLUSH_SLEEP klättrade upp – men har i jämförelse med det första testet mycket liknande ackumulerad väntetid (120 046 vs. 120 006) – och min kollega Erin Stellato (@erinstellato) pratade om just denna väntetyp i sitt inlägg. . Så om man tittar på de andra väntetyperna är det ingen som hoppar ut som en pålitlig röd flagga.

Server-Side Spåra skrivning till en långsam I/O-väg

Vad händer om vi lägger spårningsfilen på serversidan på långsam disk? Följande tabell visar före- och efter-batchbegäranden per sekund när du aktiverar en lokal spårning på serversidan som skriver till en fil på ett USB-minne:

Baslinjebatchbegäranden per sekund
(2 minuter i genomsnitt)
SQL Profiler Batch Requests per Second
(2 minuter i genomsnitt)
14 492 260

Som vi kan se – är prestandan avsevärt försämrad – även jämfört med föregående test.

De bästa väntetyperna var följande:

wait_type waiting_tasks_count väntetid_ms
SQLTRACE_FILE_BUFFER 357 351 174
SP_SERVER_DIAGNOSTICS_SLEEP 2 273 299 995
SLEEP_TASK 240 194 264
FT_IFTS_SCHEDULER_IDLE_WAIT 2 181 458
REQUEST_FOR_DEADLOCK_SEARCH 25 125 007
LAZYWRITER_SLEEP 63 124 437
LOGMGR_QUEUE 941 120 559
HADR_FILESTREAM_IOMGR_IOCOMPLETION 67 120 516
VÄNTA 1 120 515
DIRTY_PAGE_POLL 1 204 120 513

En väntetyp som hoppar ut för detta test är den odokumenterade SQLTRACE_FILE_BUFFER . Inte mycket dokumenterat om den här, men baserat på namnet kan vi göra en välgrundad gissning (särskilt med tanke på det här testets konfiguration).

Utökade händelser till ringbuffertmålet

Låt oss sedan gå igenom resultaten för motsvarande sessioner för utökad evenemang. Jag använde följande sessionsdefinition:

CREATE EVENT SESSION [ApplicationXYZ] ON SERVER
  ADD EVENT sqlserver.query_post_execution_showplan,
  ADD TARGET package0.ring_buffer(SET max_events_limit=(1000))
  WITH (STARTUP_STATE=ON);
GO

Följande tabell visar batchförfrågningar före och efter per sekund när en XE-session aktiveras med ett ringbuffertmål (fångar query_post_execution_showplan händelse):

Baslinjebatchbegäranden per sekund
(2 minuter i genomsnitt)
SQL Profiler Batch Requests per Second
(2 minuter i genomsnitt)
14 492 4 737

De bästa väntetyperna var följande:

wait_type waiting_tasks_count väntetid_ms
SP_SERVER_DIAGNOSTICS_SLEEP 612 299 992
FT_IFTS_SCHEDULER_IDLE_WAIT 4 237 006
SLEEP_TASK 240 181 739
LAZYWRITER_SLEEP 120 120 219
HADR_WORK_QUEUE 12 120 038
DIRTY_PAGE_POLL 1 198 120 035
REQUEST_FOR_DEADLOCK_SEARCH 24 120 017
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 011
LOGMGR_QUEUE 936 120 008
VÄNTA 1 120 001

Ingenting hoppade ut som XE-relaterat, bara bakgrundsuppgift "brus".

Utökade händelser till ett filmål

Vad sägs om att ändra sessionen till att använda ett filmål istället för ett ringbuffertmål? Följande tabell visar före- och efter-batchbegäranden per sekund när du aktiverar en XE-session med ett filmål istället för ett ringbuffertmål:

Baslinjebatchbegäranden per sekund
(2 minuter i genomsnitt)
SQL Profiler Batch Requests per Second
(2 minuter i genomsnitt)
14 492 4 299

De bästa väntetyperna var följande:

wait_type waiting_tasks_count väntetid_ms
SP_SERVER_DIAGNOSTICS_SLEEP 2 103 299 996
FT_IFTS_SCHEDULER_IDLE_WAIT 4 237 003
SLEEP_TASK 253 180 663
LAZYWRITER_SLEEP 120 120 187
HADR_WORK_QUEUE 12 120 029
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 019
REQUEST_FOR_DEADLOCK_SEARCH 24 120 011
VÄNTA 1 120 001
XE_TIMER_EVENT 59 119 966
LOGMGR_QUEUE 935 119 957

Ingenting, med undantag för XE_TIMER_EVENT , hoppade ut som XE-relaterad. Bob Wards Wait Type Repository hänvisar till den här som säker att ignorera om det inte var något möjligt fel - men realistiskt sett skulle du märka denna vanligtvis godartade väntetyp om den var på plats 9 på ditt system under en prestandaförsämring? Och vad händer om du redan filtrerar bort det på grund av dess normalt godartade natur?

Utökade händelser till ett långsamt I/O-sökvägsfilmål

Vad händer nu om jag lägger filen på en långsam I/O-väg? Följande tabell visar batchförfrågningar före och efter per sekund när du aktiverar en XE-session med ett filmål på ett USB-minne:

Baslinjebatchbegäranden per sekund
(2 minuter i genomsnitt)
SQL Profiler Batch Requests per Second
(2 minuter i genomsnitt)
14 492 4 386

De bästa väntetyperna var följande:

wait_type waiting_tasks_count väntetid_ms
FT_IFTS_SCHEDULER_IDLE_WAIT 4 237 046
SLEEP_TASK 253 180 719
HADR_FILESTREAM_IOMGR_IOCOMPLETION 240 120 427
LAZYWRITER_SLEEP 120 120 190
HADR_WORK_QUEUE 12 120 025
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 013
REQUEST_FOR_DEADLOCK_SEARCH 24 120 011
VÄNTA 1 120 002
DIRTY_PAGE_POLL 1 197 119 977
XE_TIMER_EVENT 59 119 949

Återigen, inget XE-relaterat hoppar ut förutom XE_TIMER_EVENT .

Utökade händelser till ett långsamt I/O-sökvägsfilmål, ingen händelseförlust

Följande tabell visar före- och efter-batchförfrågningar per sekund när du aktiverar en XE-session med ett filmål på ett USB-minne, men den här gången utan att tillåta händelseförlust (EVENT_RETENTION_MODE=NO_EVENT_LOSS) – vilket inte rekommenderas och du kommer att se i resultaten varför det kan vara:

Baslinjebatchbegäranden per sekund
(2 minuter i genomsnitt)
SQL Profiler Batch Requests per Second
(2 minuter i genomsnitt)
14 492 539

De bästa väntetyperna var följande:

wait_type waiting_tasks_count väntetid_ms
XE_BUFFERMGR_FREEBUF_EVENT 8 773 1 707 845
FT_IFTS_SCHEDULER_IDLE_WAIT 4 237 003
SLEEP_TASK 337 180 446
LAZYWRITER_SLEEP 120 120 032
DIRTY_PAGE_POLL 1 198 120 026
HADR_WORK_QUEUE 12 120 009
REQUEST_FOR_DEADLOCK_SEARCH 24 120 007
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 006
VÄNTA 1 120 000
XE_TIMER_EVENT 59 119 944

Med den extrema genomströmningsminskningen ser vi XE_BUFFERMGR_FREEBUF_EVENT hoppa till nummer ett på våra ackumulerade väntetidsresultat. Den här är dokumenteras i Books Online, och Microsoft berättar för oss att denna händelse är associerad med XE-sessioner som är konfigurerade för ingen händelseförlust och där alla buffertar i sessionen är fulla.

Observatörspåverkan

Bortsett från väntetyperna var det intressant att notera vilken inverkan varje observationsmetod hade på vår arbetsbelastnings förmåga att behandla batchförfrågningar:


Inverkan av olika observationsmetoder på batchförfrågningar per sekund

För alla tillvägagångssätt fanns det en signifikant – men inte chockerande – träff jämfört med vår baslinje (ingen observation); Den största smärtan kändes dock när du använde Profiler, när du använde Server-Side Trace till en långsam I/O-sökväg, eller utökade händelser till ett filmål på en långsam I/O-sökväg – men bara när den konfigurerades för ingen händelseförlust. Med händelseförlust fungerade den här installationen faktiskt i nivå med ett filmål till en snabb I/O-sökväg, förmodligen för att den kunde släppa mycket fler händelser.

Sammanfattning

Jag testade inte alla möjliga scenarier och det finns säkert andra intressanta kombinationer (för att inte tala om olika beteenden baserade på SQL Server-versionen), men den viktigaste slutsatsen jag drar från denna utforskning är att du inte alltid kan lita på en uppenbar ackumulering av väntetyp. pekare när du står inför ett observatörsscenario. Baserat på testerna i det här inlägget, visade endast tre av sju scenarier en specifik väntetyp som potentiellt skulle kunna hjälpa dig att peka i rätt riktning. Redan då – dessa tester var på ett kontrollerat system – och ofta filtrerar folk bort de tidigare nämnda väntetyperna som godartade bakgrundstyper – så att du kanske inte ser dem alls.

Med tanke på detta, vad kan du göra? För prestandaförsämring utan tydliga eller uppenbara symtom, rekommenderar jag att du breddar omfattningen för att fråga om spår och XE-sessioner (som en åtskillnad – jag rekommenderar också att du utökar omfattningen om systemet är virtualiserat eller kan ha felaktiga strömalternativ). Till exempel, som en del av felsökning av ett system, kontrollera sys.[traces] och sys.[dm_xe_sessions] för att se om något körs på systemet som är oväntat. Det är ett extra lager till det du behöver oroa dig för, men att göra några snabba valideringar kan spara en hel del tid.


  1. SQL Server Agent Alerts

  2. Hur Replace() fungerar i SQLite

  3. Skickar parametrar till en JDBC PreparedStatement

  4. Använda SSH Tunneling som ett VPN-alternativ