Database
 sql >> Database >  >> RDS >> Database

Sovraccarico dell'osservatore e sintomi del tipo di attesa

Molte persone usano le statistiche di attesa come parte della loro metodologia generale di risoluzione dei problemi delle prestazioni, così come me, quindi la domanda che volevo esplorare in questo post riguarda i tipi di attesa associati al sovraccarico dell'osservatore. Per sovraccarico dell'osservatore, intendo l'impatto sul throughput del carico di lavoro di SQL Server causato da SQL Profiler, tracce lato server o sessioni di eventi estesi. Per ulteriori informazioni sull'argomento dell'osservatore dall'alto, vedere i seguenti due post del mio collega Jonathan Kehayias :

  • Misurazione del "overhead dell'osservatore" di SQL Trace rispetto agli eventi estesi
  • Impatto dell'evento esteso query_post_execution_showplan in SQL Server 2012

Quindi in questo post vorrei esaminare alcune variazioni dell'osservatore sopra la testa e vedere se riusciamo a trovare tipi di attesa coerenti associati al degrado misurato. Esistono diversi modi in cui gli utenti di SQL Server implementano la traccia nei loro ambienti di produzione, quindi i risultati possono variare, ma volevo coprire alcune categorie generali e riferire su ciò che ho trovato:

  • Utilizzo della sessione di SQL Profiler
  • Utilizzo della traccia lato server
  • Utilizzo della traccia lato server, scrittura su un percorso I/O lento
  • Utilizzo di eventi estesi con una destinazione buffer ad anello
  • Utilizzo di eventi estesi con un file di destinazione
  • Utilizzo di eventi estesi con un file di destinazione su un percorso I/O lento
  • Utilizzo di eventi estesi con un file di destinazione su un percorso I/O lento senza perdita di eventi

È probabile che tu possa pensare ad altre variazioni sul tema e ti invito a condividere eventuali scoperte interessanti relative al sovraccarico dell'osservatore e ad attendere le statistiche come commento in questo post.

Linea di base

Per il test ho utilizzato una macchina virtuale VMware con quattro vCPU e 4 GB di RAM. Il mio ospite della macchina virtuale era su SSD OCZ Vertex. Il sistema operativo era Windows Server 2008 R2 Enterprise e la versione di SQL Server è 2012, SP1 CU4.

Per quanto riguarda il "carico di lavoro", sto utilizzando una query di sola lettura in loop rispetto al database di esempio del credito 2008, impostato su GO 10.000.000 di volte.

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

Sto anche eseguendo questa query tramite 16 sessioni simultanee. Il risultato finale sul mio sistema di test è l'utilizzo della CPU al 100% su tutte le vCPU sul guest virtuale e una media di 14.492 richieste batch al secondo in un periodo di 2 minuti.

Per quanto riguarda il tracciamento degli eventi, in ogni test ho utilizzato Showplan XML Statistics Profile per i test di traccia SQL Profiler e lato server e query_post_execution_showplan per le sessioni di eventi estesi. Gli eventi del piano di esecuzione sono molto costosi, motivo per cui li ho scelti in modo da poter vedere se in circostanze estreme potevo ricavare o meno temi di tipo wait.

Per testare l'accumulo del tipo di attesa in un periodo di prova, ho utilizzato la query seguente. Niente di speciale:basta cancellare le statistiche, attendere 2 minuti e quindi raccogliere i primi 10 accumuli di attesa per l'istanza di SQL Server durante il periodo di test di degradazione:

-- 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;

Nota che non lo sono filtrando i tipi di attesa in background che sono generalmente filtrati, e questo perché non volevo eliminare qualcosa che normalmente è benigno, ma in questa circostanza indica effettivamente un'area reale su cui indagare ulteriormente.

Sessione SQL Profiler

La tabella seguente mostra le richieste batch prima e dopo al secondo quando si abilita un tracciamento di traccia SQL Profiler locale Showplan XML Statistics Profile (in esecuzione sulla stessa macchina virtuale dell'istanza di SQL Server):

Richieste batch di riferimento al secondo
(media di 2 minuti)
Richieste batch di sessioni di SQL Profiler al secondo
(media di 2 minuti)
14.492 1.416

È possibile notare che la traccia di SQL Profiler provoca un calo significativo della velocità effettiva.

Per quanto riguarda il tempo di attesa accumulato nello stesso periodo, i principali tipi di attesa erano i seguenti (come per il resto dei test in questo articolo, ho eseguito alcuni test e l'output è stato generalmente coerente):

wait_type waiting_tasks_count wait_time_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
PAGINA_DIRTY_POLL 1.198 120.038
HADR_WORK_QUEUE 12 120.015
LOGMGR_QUEUE 937 120.011
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120.006

Il tipo di attesa che mi viene visualizzato è TRACEWRITE – che è definito dalla documentazione in linea come un tipo di attesa che "si verifica quando il provider di traccia del set di righe di SQL Trace attende un buffer libero o un buffer con eventi da elaborare". Il resto dei tipi di attesa sembrano tipi di attesa in background standard che in genere vengono filtrati dal set di risultati. Inoltre, ho parlato di un problema simile con la traccia eccessiva in un articolo del 2011 intitolato Observer overhead – i pericoli di una traccia eccessiva – quindi avevo familiarità con questo tipo di attesa a volte indicando correttamente i problemi di overhead dell'osservatore. Ora, in quel caso particolare di cui ho parlato nel blog, non era SQL Profiler, ma un'altra applicazione che utilizzava il provider di traccia del set di righe (in modo inefficiente).

Traccia lato server

Era per SQL Profiler, ma per quanto riguarda l'overhead di traccia lato server? La tabella seguente mostra le richieste batch prima e dopo al secondo quando si abilita una traccia lato server locale che scrive su un file:

Richieste batch di riferimento al secondo
(media di 2 minuti)
Richieste batch di SQL Profiler al secondo
(media di 2 minuti)
14.492 4.015

I principali tipi di attesa erano i seguenti (ho eseguito alcuni test e l'output è stato coerente):

wait_type waiting_tasks_count wait_time_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
ATTENDERE 1 120.000
LOGMGR_QUEUE 931 119.993
PAGINA_DIRTY_POLL 1.193 119.958
XE_TIMER_EVENT 55 119.954

Questa volta non vediamo TRACEWRITE (stiamo utilizzando un provider di file ora) e l'altro tipo di attesa relativo alla traccia, il SQLTRACE_INCREMENTAL_FLUSH_SLEEP non documentato è salito – ma rispetto al primo test ha un tempo di attesa accumulato molto simile (120.046 contro 120.006) – e la mia collega Erin Stellato (@erinstellato) ha parlato di questo particolare tipo di attesa nel suo post Capire quando le statistiche di attesa sono state cancellate per l'ultima volta . Quindi, guardando gli altri tipi di attesa, nessuno salta fuori come una bandiera rossa affidabile.

Traccia lato server in scrittura su un percorso I/O lento

Cosa succede se mettiamo il file di traccia lato server su disco lento? La tabella seguente mostra le richieste batch prima e dopo al secondo quando si abilita una traccia lato server locale che scrive su un file su una chiavetta USB:

Richieste batch di riferimento al secondo
(media di 2 minuti)
Richieste batch di SQL Profiler al secondo
(media di 2 minuti)
14.492 260

Come possiamo vedere – le prestazioni sono notevolmente degradate – anche rispetto al test precedente.

I principali tipi di attesa erano i seguenti:

wait_type waiting_tasks_count wait_time_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
ATTENDERE 1 120.515
PAGINA_DIRTY_POLL 1.204 120.513

Un tipo di attesa che salta fuori per questo test è SQLTRACE_FILE_BUFFER non documentato . Non molto documentato su questo, ma in base al nome, possiamo fare un'ipotesi plausibile (soprattutto vista la configurazione di questo particolare test).

Eventi estesi alla destinazione del buffer dell'anello

Quindi esaminiamo i risultati per gli equivalenti della sessione di eventi estesi. Ho usato la seguente definizione di sessione:

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

La tabella seguente mostra le richieste batch prima e dopo al secondo quando si abilita una sessione XE con una destinazione buffer ad anello (catturando il query_post_execution_showplan evento):

Richieste batch di riferimento al secondo
(media di 2 minuti)
Richieste batch di SQL Profiler al secondo
(media di 2 minuti)
14.492 4.737

I principali tipi di attesa erano i seguenti:

wait_type waiting_tasks_count wait_time_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
PAGINA_DIRTY_POLL 1.198 120.035
REQUEST_FOR_DEADLOCK_SEARCH 24 120.017
SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120.011
LOGMGR_QUEUE 936 120.008
ATTENDERE 1 120.001

Niente è saltato fuori come "rumore" relativo a XE, solo attività in background.

Eventi estesi a un file di destinazione

Che ne dici di modificare la sessione per utilizzare una destinazione file invece di una destinazione buffer ad anello? La tabella seguente mostra le richieste batch prima e dopo al secondo quando si abilita una sessione XE con una destinazione file anziché una destinazione buffer ad anello:

Richieste batch di riferimento al secondo
(media di 2 minuti)
Richieste batch di SQL Profiler al secondo
(media di 2 minuti)
14.492 4.299

I principali tipi di attesa erano i seguenti:

wait_type waiting_tasks_count wait_time_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
ATTENDERE 1 120.001
XE_TIMER_EVENT 59 119.966
LOGMGR_QUEUE 935 119.957

Niente, ad eccezione di XE_TIMER_EVENT , è saltato fuori come relativo a XE. Il Wait Type Repository di Bob Ward si riferisce a questo come sicuro da ignorare a meno che non ci sia qualcosa che non va, ma realisticamente noteresti questo tipo di attesa solitamente benigno se fosse al 9 posto sul tuo sistema durante un degrado delle prestazioni? E se lo stai già filtrando a causa della sua natura normalmente benigna?

Eventi estesi a una destinazione file di percorso I/O lenta

Ora cosa succede se metto il file su un percorso di I/O lento? La tabella seguente mostra le richieste batch prima e dopo al secondo quando si abilita una sessione XE con un file di destinazione su una chiavetta USB:

Richieste batch di riferimento al secondo
(media di 2 minuti)
Richieste batch di SQL Profiler al secondo
(media di 2 minuti)
14.492 4.386

I principali tipi di attesa erano i seguenti:

wait_type waiting_tasks_count wait_time_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
ATTENDERE 1 120.002
PAGINA_DIRTY_POLL 1.197 119.977
XE_TIMER_EVENT 59 119.949

Ancora una volta, nulla relativo a XE salta fuori tranne il XE_TIMER_EVENT .

Eventi estesi a un file di destinazione del percorso I/O lento, nessuna perdita di eventi

La tabella seguente mostra le richieste batch prima e dopo al secondo quando si abilita una sessione XE con un file di destinazione su una chiavetta USB, ma questa volta senza consentire la perdita di eventi (EVENT_RETENTION_MODE=NO_EVENT_LOSS) – che non è consigliato e vedrai nei risultati perché potrebbe essere:

Richieste batch di riferimento al secondo
(media di 2 minuti)
Richieste batch di SQL Profiler al secondo
(media di 2 minuti)
14.492 539

I principali tipi di attesa erano i seguenti:

wait_type waiting_tasks_count wait_time_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
PAGINA_DIRTY_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
ATTENDERE 1 120.000
XE_TIMER_EVENT 59 119.944

Con l'estrema riduzione del throughput, vediamo XE_BUFFERMGR_FREEBUF_EVENT salta alla posizione numero uno nei risultati del tempo di attesa accumulato. Questo è documentato nella documentazione in linea e Microsoft ci dice che questo evento è associato a sessioni XE configurate per nessuna perdita di eventi e in cui tutti i buffer della sessione sono pieni.

Impatto dell'osservatore

A parte i tipi di attesa, è stato interessante notare quale impatto ha avuto ciascun metodo di osservazione sulla capacità del nostro carico di lavoro di elaborare le richieste batch:


Impatto di diversi metodi di osservazione sulle richieste batch al secondo

Per tutti gli approcci, c'è stato un colpo significativo, ma non scioccante, rispetto alla nostra linea di base (nessuna osservazione); il problema maggiore, tuttavia, è stato avvertito quando si utilizza Profiler, quando si utilizza la traccia lato server su un percorso I/O lento o gli eventi estesi su una destinazione file su un percorso I/O lento, ma solo se configurato per nessuna perdita di eventi. Con la perdita di eventi, questa configurazione ha effettivamente funzionato alla pari con un file di destinazione su un percorso I/O veloce, presumibilmente perché è stato in grado di eliminare molti più eventi.

Riepilogo

Non ho testato tutti gli scenari possibili e ci sono sicuramente altre combinazioni interessanti (per non parlare dei diversi comportamenti basati sulla versione di SQL Server), ma la conclusione chiave che traggo da questa esplorazione è che non puoi sempre fare affidamento su un ovvio accumulo di tipi di attesa puntatore quando ci si trova di fronte a uno scenario dall'alto dell'osservatore. Sulla base dei test in questo post, solo tre scenari su sette hanno manifestato un tipo di attesa specifico che potrebbe potenzialmente aiutarti a indirizzarti nella giusta direzione. Anche allora, questi test erano su un sistema controllato e spesso le persone filtrano i suddetti tipi di attesa come tipi di background benigni, quindi potresti non vederli affatto.

Detto questo, cosa puoi fare? Per un degrado delle prestazioni senza sintomi chiari o evidenti, consiglio di ampliare l'ambito per chiedere informazioni su tracce e sessioni XE (per inciso, consiglio anche di ampliare l'ambito se il sistema è virtualizzato o potrebbe avere opzioni di alimentazione errate). Ad esempio, come parte della risoluzione dei problemi di un sistema, controlla sys.[traces] e sys.[dm_xe_sessions] per vedere se sul sistema è in esecuzione qualcosa di imprevisto. È un livello in più rispetto a ciò di cui devi preoccuparti, ma eseguire alcune rapide convalide potrebbe farti risparmiare una notevole quantità di tempo.