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

Risoluzione dei problemi di query a esecuzione prolungata in MS SQL Server

Prefazione

C'è un sistema informativo che gestisco. Il sistema è composto dai seguenti componenti:

1. Database MS SQL Server
2. Applicazione server
3. Applicazioni client

Questi sistemi informativi sono installati su più oggetti. Il sistema informativo è utilizzato attivamente 24 ore su 24 da 2 a 20 utenti contemporaneamente su ciascun oggetto. Pertanto, non è possibile eseguire la manutenzione ordinaria tutta in una volta. Quindi, devo «distribuire» la deframmentazione dell'indice di SQL Server durante il giorno, piuttosto che deframmentare tutti gli indici frammentati necessari in un colpo solo. Questo vale anche per altre operazioni.

La proprietà di aggiornamento automatico delle statistiche è impostata nelle proprietà del database. Inoltre, le statistiche vengono aggiornate sull'indice deframmentato.

Problema

Circa un anno fa, ho riscontrato il seguente problema:

Di tanto in tanto, tutte le query erano lente. In particolare, il tempo di ritardo era casuale. È successo su ogni oggetto in un giorno casuale. Inoltre, quando ho iniziato ad analizzare la frequenza con cui si verificano i ritardi (usando il profiler), ho scoperto che si verificano ogni giorno a un'ora casuale. Gli utenti semplicemente non prestano loro attenzione, ma li considerano come l'unico ritardo casuale, quindi il sistema funziona di nuovo rapidamente.

Risolvere il problema

Ho esaminato tutte le query a esecuzione lenta. La cosa più strana era che tutte le query funzionavano lentamente in un momento casuale, anche le più semplici, come estrarre l'ultimo record da una tabella con diverse migliaia di righe.

Inoltre, ho eseguito i seguenti passaggi:

1. Ho analizzato i log di MS SQL Server e Windows Server, ma non sono riuscito a trovare la causa dei ritardi.
2. Ho analizzato gli indici (frammentazione, ecc.), aggiunto quelli mancanti e rimosso quelli inutilizzati.
3. Ho analizzato le query:alcune query sono state migliorate.
4. Ho analizzato le attività in SQL Agent e non sono riuscito ad associare le attività al problema del ritardo.
5. Ho analizzato le attività in Utilità di pianificazione e non sono riuscito ad associare le attività al problema del ritardo.
6. Profiler ha mostrato i risultati, ma non la causa dei ritardi.
7. Ho eseguito un controllo dei deadlock:non sono stati rilevati blocchi lunghi.

Di conseguenza, ho trascorso più di 3 mesi nella ricerca senza successo del motivo di query occasionali a esecuzione lenta. Tuttavia, ho rivelato un fatto interessante:invece dell'indicatore di esecuzione di Worker, l'indicatore di attesa trascorsa è aumentato per tutte le query. Questo fatto mi ha dato l'idea che qualcosa non va con i dischi. Li ho controllati:era tutto a posto.

Soluzione

Con mia sorpresa, ho accidentalmente rivelato che quando una query veniva eseguita lentamente nell'applicazione, veniva eseguita rapidamente in SSMS. Un articolo ha aiutato a risolvere il problema (almeno ha suggerito l'idea).

Un paragrafo dell'articolo:

In pratica, l'opzione SET più importante è ARITHABORT, perché il valore predefinito per questa opzione è diverso per le applicazioni e per SQL Server Management Studio. Questo spiega perché è possibile rilevare una query a esecuzione lenta nell'applicazione e quindi ottenere una buona velocità eseguendola in SSMS. L'applicazione utilizza un piano che è stato creato per un insieme di valori che differisce dai valori effettivi corretti. Considerando che se si esegue la query in SSMS, è molto probabile che la cache non disponga ancora di un piano di esecuzione per ARITHABORT ON e pertanto SQL Server creerà un piano per i valori correnti.

La differenza di esecuzione era dovuta al parametro SET ARITHABORT. Per tutte le query eseguite in SSMS, questa opzione è abilitata e per le query dall'esterno (dalle applicazioni) – disabilitata. Non può essere abilitato nemmeno con una semplice query per le applicazioni:

SET ARITHABORT ON;

Ne è seguita un'idea pazza:svuotare la cache procedurale al momento del riaggancio.

Per il successivo controllo manuale, devo scrivere la seguente istruzione prima della query in SSMS:

SET ARITHABORT OFF;

Quindi simuleremo il funzionamento dell'applicazione. Quando la query era in esecuzione da molto tempo, ho svuotato la cache procedurale. E questo ha sempre aiutato. Prima di svuotare la cache procedurale, la query potrebbe durare fino a 20-30 secondi e, successivamente, 0 secondi.

Successivamente, ho eseguito un altro esperimento:pulire l'intera cache procedurale per l'intero database ogni ora tramite SQL Agent:

--cleaning the cache by database id
DBCC FLUSHPROCINDB (@db_id);

Successivamente, tutte le query sono state eseguite molto rapidamente (meno di 0,05 secondi). Si sono verificate solo alcune occorrenze fino a 5-10 secondi di esecuzione, ma gli utenti non hanno notato alcun blocco. Inoltre, l'aggiornamento delle statistiche non ha migliorato i risultati, quindi ho disabilitato l'aggiornamento delle statistiche.

Dopo qualche altro mese di studio, ho scoperto che si verificano occasionali blocchi quando o la cache consuma tutto sul server e non è rimasto spazio libero o c'è memoria libera, ma meno di 1 GB di RAM o il servizio MS SQL Server occupa tutta la RAM allocata (tramite Task Manager). Ma il secondo evento si è verificato solo due volte nell'intero studio.

Il fatto è che letteralmente tutto viene scritto nella cache, mentre la cache non viene sempre rilasciata in tempo. Il problema con la cache è stato risolto utilizzando il programma EmptyStandbyList.exe.

Ho configurato questa applicazione tramite Utilità di pianificazione per l'esecuzione 1 volta ogni ora. Dopo tutto il lavoro svolto, da più di sei mesi ormai non ci sono interruzioni di query su tutti gli oggetti.

L'unica cosa che non è chiara sono i rari casi in cui una query si blocca per 5-10 secondi una volta al mese in un giorno e in un'ora casuali. Si sono verificati 4 casi di questo tipo e solo su due oggetti per sei mesi quando il servizio MS SQL Server ha occupato tutta la memoria allocata per un breve periodo di tempo.

Fondamentalmente, non è necessario scavare più a fondo, poiché gli utenti non notano alcun blocco e tutto funziona bene, ma se qualcuno ha qualche idea, sarò grato per la condivisione.

Questo articolo è stato scritto per aiutare coloro che incontrano tali problemi, poiché non ho trovato una risposta esauriente su Internet e ho dedicato molto tempo allo studio del problema e alla ricerca della soluzione.

Vedi anche:

  1. Implementazione dell'indicatore delle prestazioni di SQL Server per query, stored procedure e trigger
  2. Automazione della deframmentazione degli indici nel database di MS SQL Server


Strumento utile:

dbForge Query Builder per SQL Server:consente agli utenti di creare query SQL complesse in modo rapido e semplice tramite un'interfaccia visiva intuitiva senza la scrittura manuale del codice.