Proseguiamo con la nostra panoramica dopo i controlli visti nell'articolo precedente.
Proprietà dei database presenti in un'istanza
Con il codice sotto andremo ad estrarre importanti proprietà di tutti i database presenti nell’istanza. Informazioni come il Recovery Model, il riutilizzo del Log, il compatibility level, sono alcuni importanti dettagli che la query ci mostra. Ad esempio nel caso di database in Recovery Model in FULL, è fortemente consigliato implementare un backup del transaction log, altrimenti il log crescerebbe fino a saturare il disco oppure lo spazio a disposizione impostato per il t-log. Analizzando gli altri risultati, possiamo scoprire se il t-log sta per riempirsi, oppure se sono attive le auto-statistiche o l’auto-skrink.
Volendo scoprire invece quali database sono maggiormente soggetti a blocchi i I/O, possiamo utilizzare:
L’output mostra il tempo di stallo I/O in millesecondi, di conseguenza è possibile determinare quale database ha impegnato più wait di attesa I/O. La query sopra mostra anche le attività di lettura e scrittura per tutti i database. Se si notano molti record riferiti allo stesso database in alto all’output dei risultati di questa query, potrebbe indicare dei colli di bottiglia riferiti all’I/O del disco; in tal caso per dare fondamenta solide al sospetto, occorre fare riferimento ai performance counter di windows come Avg Disk Sec/Write e Avg Sec/Read.
Utilizzo della CPU
La query sopra elencherà l’utilizzo totale del buffer per ogni database utente in esecuzione sull’istanza corrente. Per ridurre l’utilizzo della memoria di un particolare database si può tentare di verificare eventuali indici mancanti su tabelle di grandi dimensioni che causano di conseguenza un gran numero di scansioni di indici o tabelle.
Nel caso si abbia a che fare con la versione Enterprise di SQL server, si può iniziare ad utilizzare la compressione dei dati di SQL Server su alcuni degli indici più grandi. Prima di fare ciò, è comunque necessario verificare che si tratti di una tabella statica di grandi dimensioni altamente comprimibile a causa dei tipi di dati e dei dati effettivi in tabella. Un indice compresso rimarrà compresso nel buffer pool a meno che i dati non vengano aggiornati.
Proseguendo con le analisi tramite la query successiva, è possibile estrarre dati sulla quantità di tempo di utilizzo dei processori da parte degli user database:
L’utilizzo di questa query è limitato all’utilizzo del comando DBCC FLUSHPROCINDB(database_id), in quanto questo comando cancella la cache dei piani; di conseguenza viene eliminato anche l’utilizzo complessivo della CPU da parte dei database.
Statistiche di attesa
La query seguente invece prende in esame le principali statistiche di attesa cumulative dall’ultimo avvio di SQL Server o da quando le stesse sono state cancellate mediante l’utilizzo del comando DBCC SQLPERF(‘sys.dm_os_wait_stats’, CLEAR):
La query appena esposta aiuta a concentrarsi sui maggiori tempi di attesa di SQL Server. Bisogna ricordarsi che si tratta comunque di tempi di attesa registrati dall’ultimo riavvio di SQL Server e che non tutti i tempi di attesa sono dannosi per l’istanza. Nella clausola NOT IN della query sono stati esclusi i wait che risultano essere benigni e quindi possono essere ignorati.
A seconda della percentuale rilevata tramite la query sopra, si può decidere di indagare in maniera mirata sugli eventi che stanno scatenando un accumulo elevato del wait in questione.
Sempre collegato ai waits, SignalWait riguarda le attese legate alla CPU. La query seguente cerca di rilevare eventuali segnali di pressione sulla CPU. Un segnale di attesa che supera il 15%-20% è già un rilevatore di pressione per la CPU.
Ecco un esempio di output:
Riguardo le connessioni, la seguente query invece siamo in grado di verificare il numero di connessioni verso il database da parte delle singole login.
Rilevare il numero di connessioni per ciascun accesso permette di valutare eventuali carichi di lavoro che si discostano dalla normale routine quotidiana.
La seguente query invece mostra le attività correnti ed altre informazioni sull’I/O in sospeso.
A seconda dei valori ricevuti da questa query possiamo ricavare varie informazioni.
AVG Task Count: (per scheduler della CPU) è un buon indicatore del livello complessivo del carico di lavoro. Un numero elevato in questa colonna indica problemi causati da blocchi o conflitti di risorse.
AVG Runnable Task Count: indica quante attività sono in attesa della CPU su ciascuno scheduler. Valori elevati (superiore a 10), indicano pressione verso la CPU.
AVG Pending DiskIOCount: misura il numero di operazioni I/O in sospeso presenti su ogni scheduler della CPU, di conseguenza, valori superiori a 10 indicano pressione sull’I/O complessivo. Quest’ultimo valore, nel caso il sistema sia sottopressione, cambierà molto velocemente.
Se vogliamo utilizzare la query sopra per il nostro sistema di Health Check, ricordiamoci che dobbiamo prevedere un polling molto ravvicinato poiché, come prevedibile, i valori cambiano molto velocemente a seconda del carico di lavoro. Se uno dei 3 valori restituiti dalla query, rimane con un valore superiore a 10 per lunghi periodi, è il caso di sospettare che qualcosa non stia andando per il verso giusto.
Ancora sulla CPU la seguente query, mostra l’utilizzo della CPU negli ultimi 256 minuti ad intervalli di 1 minuto.
L’output della query mostra, l’utilizzo delle CPU di SQL Server, Idle, degli altri processi e l’intervallo considerato.
Nella terza ed ultima parte vedremo come effettuare i controlli a livello di memoria ed indici.
di Luciano Maugeri, pubblicato il 29 aprile 2026