Flush della cache di SQL Server e I / O del disco


11

Siamo impegnati a testare un sistema OLTP che abbiamo sviluppato in .NET 4.0 ed esegue SQL Server 2008 R2 sul retro. Il sistema utilizza le code di SQL Server Service Broker, che sono molto performanti, ma stiamo riscontrando una tendenza peculiare durante l'elaborazione.

Richieste di processo di SQL Server a una velocità elevata per 1 minuto, seguite da ~ 20 secondi di maggiore attività di scrittura su disco. Il seguente grafico illustra il problema.

Sistema SQL OLTP - Contatori delle prestazioni

Yellow = Transactions per second
Blue   = Total CPU usage
Red    = Sqlsrv Disk Write Bytes/s
Green  = Sqlsrv Disk Read Bytes/s

Durante la risoluzione dei problemi, abbiamo provato quanto segue senza alcuna modifica significativa nel modello:

  • Agente SQL Server arrestato.
  • Ha ucciso quasi tutti gli altri processi in esecuzione (No A / V, SSMS, VS, Windows Explorer, ecc.)
  • Rimossi tutti gli altri database.
  • Disabilitato tutti i timer di conversazione (non utilizziamo trigger).
  • Allontanato da un approccio basato sulla coda dei messaggi a un design di monitoraggio della tabella semplice / grezzo.
  • Usato diversi carichi da leggero a pesante.
  • Risolti tutti i deadlock.

Sembra che SQL Server stia accumulando la sua cache e scrivendola sul disco a intervalli di tempo specifici, ma non riesco a trovare nulla online per supportare questa teoria.

Successivamente, ho intenzione di spostare la soluzione nel nostro ambiente di test dedicato per vedere se riesco a replicare il problema. Qualsiasi aiuto nel frattempo sarebbe molto apprezzato.

Aggiornamento 1 Come richiesto, con un grafico che include le pagine / sec di Checkpoint , l' aspettativa di durata della pagina e alcuni contatori di latenza del disco.

Sistema SQL OLTP - Contatori delle prestazioni - Punto di controllo

Sembra che il Checkpoint (linea blu chiaro) sia la causa della prestazione ridotta (linea gialla) che stiamo osservando. ^

La latenza del disco rimane relativamente coerente durante l'elaborazione e l'aspettativa di vita della pagina non sembra avere alcun effetto evidente. Abbiamo anche regolato la quantità di RAM disponibile per SQL Server, che non ha avuto un grande effetto. Anche la modifica del modello di recupero SIMPLEin FULLha fatto poca differenza.

Aggiornamento 2 Modificando l '"Intervallo di ripristino" come segue, siamo riusciti a ridurre l'intervallo in cui si verificano i checkpoint:

EXEC sp_configure 'show advanced options',1
GO 

RECONFIGURE
GO

EXEC sp_configure 'recovery interval', '30'
GO

RECONFIGURE 
GO

EXEC sp_configure 'show advanced options',0
GO
RECONFIGURE

Non sono sicuro che si tratti di una cattiva pratica?


1
Aggiungi il contatore pagine checkpoint / sec. E prova di nuovo e mostra il grafico. E mentre le tue transazioni diminuiscono e le scritture aumentano, riscontri problemi di prestazioni? Aggiungerei anche alcuni contatori di latenza del disco - avg sec / read e avg sec / write
Mike Walsh

E quando pubblichi i grafici successivi puoi includere i numeri. Quel grafico non mostra alcuna scala.
Mike Walsh,

5
E un'ultima cosa (scusate!) - Qual è la memoria su questo server? Puoi aggiungere anche il contatore dell'aspettativa di vita della pagina? Puoi descrivere la configurazione fisica (memoria, configurazione I / O, hai diviso il tuo registro e file di dati, ecc.)
Mike Walsh,

2
In quale modello di recupero si trova il database? Sembra un checkpoint automatico man mano che il registro delle transazioni si riempie. Si noti che anche se il database è in FULLo BULK_LOGGED, si comporta comunque come se fosse in SIMPLEfino a quando non si esegue un backup completo.
Jon Seigel,

2
Jon - Il checkpoint continuerà comunque indipendentemente dal modello di recupero. Semplificato: l'unica differenza è ciò che accade ai dati nel registro dopo un checkpoint nei modelli di recupero. In Full rimane nel registro e deve essere eseguito il backup. In parole povere può essere troncato (o contrassegnato per troncamento .. riutilizzo) ma il checkpoint deve ancora essere eseguito.
Mike Walsh,

Risposte:


11

Altri hanno già segnalato il colpevole: SQL Server accumula gli aggiornamenti in memoria (nel pool buffer) e li elimina solo periodicamente (ai punti di controllo). Le due opzioni suggerite (-k e intervallo del punto di arresto) sono complementari:

Ma non ho risposto solo per rigurgitare i bei commenti che hai ricevuto fare molto :)

Ciò che stai vedendo, sfortunatamente, è un comportamento molto tipico dell'elaborazione in coda . Sia che si utilizzino le code di Service Broker o si scelga di utilizzare le tabelle come approccio alle code , il sistema è molto incline a questo tipo di comportamento. Questo perché l'elaborazione basata su accodamento è pesante, anche più pesante dell'elaborazione OLTP. Sia accodamento e dequeue primitive sono le operazioni di scrittura e non ci sono operazioni quasi leggere. In poche parole, l'elaborazione della coda genererà il maggior numero di scritture (= pagine più sporche e la maggior parte dei registri) rispetto a qualsiasi altro carico di lavoro, anche OLTP (cioè carico di lavoro simile a TPC-C ).

Cosa molto importante, le scritture di un carico di lavoro della coda seguono un modello di inserimento / eliminazione: ogni riga inserita viene eliminata molto rapidamente. Ciò è importante per distinguere da un modello di sola aggiunta di un carico di lavoro di inserimento pesante (ETL). Fondamentalmente stai alimentando il compito di pulizia dei fantasmi un pasto completo e puoi facilmente superarlo. Pensa a cosa significa:

  • enqueue è un inserto, creerà una pagina sporca
  • dequeue è un'eliminazione, sporcherà di nuovo la stessa pagina (potrebbe essere fortunato e catturare la pagina prima del checkpoint, quindi eviterà il doppio flush, ma solo se è fortunato)
  • la pulizia fantasma pulirà la pagina, rendendola nuovamente sporca

Sì, significa davvero che potresti finire per scrivere una pagina tre volte sul disco, in tre diverse richieste IO, per ogni messaggio che elabori (caso peggiore). Significa anche che l'IO casuale dei checkpoint sarà davvero casuale poiché il punto di scrittura della pagina sarà visitato di nuovo da quelle teste mobili tra due checkpoint (il confronto con molti carichi di lavoro OLTP tende a raggruppare le scritture su alcuni "punti caldi", non code ...).

Quindi hai questi tre punti di scrittura, che corrono per contrassegnare la stessa pagina ancora e ancora. E questo prima di considerare qualsiasi divisione di pagina, anche l'elaborazione della coda potrebbe essere soggetta a causa dell'ordine di inserimento delle chiavi. In confronto, i carichi di lavoro OLTP "tipici" hanno un rapporto lettura / scrittura molto più bilanciato e le scritture OLTP sono distribuite su inserti / aggiornamenti / eliminazioni, spesso con aggiornamenti (modifiche allo "stato") e inserimenti che assumono la parte del leone. Le scritture di elaborazione delle code vengono esclusivamente inserite / eliminate con, per definizione, suddivisione 50/50.

Seguono alcune conseguenze:

  • Checkpoint diventa un problema molto caldo (non è più una sorpresa per te)
  • Vedrai una forte frammentazione (la frammentazione di per sé non avrà molta importanza in quanto non eseguirai scansioni di portata, ma l'efficienza dell'IO soffre e la pulizia dei fantasmi ha molto di più da lavorare, rallentandola ancora di più)
  • Il throughput IO casuale dell'archiviazione MDF sarà il collo di bottiglia

La mia raccomandazione arriva in 3 lettere: S, S e D. Sposta il tuo MDF in una memoria in grado di gestire I / O casuali veloci. SSD. Fusion-IO se hai i soldi. Purtroppo questo è uno di quei sintomi che non possono essere risolti con RAM più economica ...

Modificare:

Come sottolinea Mark, hai due dischi logici supportati da un disco fisico. Forse hai provato a seguire le migliori pratiche e a dividere il registro su D: e i dati su C: ma purtroppo è inutile, C e D sono lo stesso disco. Tra i checkpoint si ottiene un throughput sequenziale ma non appena si avvia il checkpoint, le testine del disco iniziano a spostarsi e il throughput del log collassa, riducendo l'intero throughput dell'app. Assicurarsi di separare il registro DB in modo che non sia interessato dai dati IO (disco separato).


2
tra l'altro sarebbe interessante sapere perché l' IO guidato dal checkpoint provoca un impatto così drammatico sui contatori delle applicazioni. Idealmente l'applicazione dovrebbe avanzare mentre il checkpoint fa il suo lavoro. Naturalmente, suppongo che tu non condivida il percorso di accesso allo storage LDF e MDF (se lo fai, te lo meriti ...). Forse hai alcuni punti di contesa non necessari nell'applicazione.
Remus Rusanu,

Risposta molto ben fatta Remus.
Mark Storey-Smith il

3
Guardando i contatori di perfmon elencati, sospetto che potresti avere ragione sui dati e sui log che si trovano sulla stessa unità o array.
Mark Storey-Smith il

@ MarkStorey-Smith: penso che tu abbia ragione, OP ha C:e D:dischi logici supportati dallo stesso disco fisico. Dubito che il disco fisico sia una batteria di 100 mandrini a strisce corte, quindi questa è probabilmente la causa principale.
Remus Rusanu il

Sì, questo test è stato eseguito sulla mia macchina di sviluppo locale, che ha una sola unità. Grazie per l'aiuto a tutti.
André Hauptfleisch,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.