Abbiamo un database di grandi dimensioni, circa 1 TB, che esegue SQL Server 2014 su un server potente. Tutto ha funzionato bene per alcuni anni. Circa 2 settimane fa abbiamo effettuato una manutenzione completa, che includeva: Installa tutti gli aggiornamenti software; ricostruire tutti gli indici e i file DB compatti. Tuttavia, non ci aspettavamo che a un certo punto l'utilizzo della CPU del DB aumentasse di oltre il 100% al 150% quando il carico effettivo era lo stesso.
Dopo un sacco di risoluzione dei problemi, l'abbiamo ridotto a una query molto semplice, ma non siamo riusciti a trovare una soluzione. La query è estremamente semplice:
select top 1 EventID from EventLog with (nolock) order by EventID
Ci vogliono sempre circa 1,5 secondi! Tuttavia, una query simile con "desc" richiede sempre circa 0 ms:
select top 1 EventID from EventLog with (nolock) order by EventID desc
PTable ha circa 500 milioni di righe; EventID
è la colonna dell'indice cluster primario (ordinata ASC
) con il tipo di dati bigint (colonna Identity). Esistono più thread che inseriscono i dati nella tabella in alto (EventID più grandi) e 1 thread elimina i dati dal basso (EventID più piccoli).
In SMSS, abbiamo verificato che le due query utilizzano sempre lo stesso piano di esecuzione:
Scansione indice cluster;
I numeri di riga stimati ed effettivi sono entrambi 1;
Il numero stimato ed effettivo di esecuzioni sono entrambi 1;
Il costo I / O stimato è 8500 (sembra essere elevato)
Se eseguito consecutivamente, il costo della query è lo stesso 50% per entrambi.
Ho aggiornato le statistiche dell'indice with fullscan
, il problema persisteva; Ho ricostruito di nuovo l'indice e il problema sembrava essere scomparso per mezza giornata, ma è tornato.
Ho attivato le statistiche IO con:
set statistics io on
quindi ha eseguito le due query consecutive e ha trovato le seguenti informazioni:
(Per la prima query, quella lenta)
Tabella "PTable". Conteggio scansioni 1, letture logiche 407670, letture fisiche 0, letture read-ahead 0, letture log lob 0, letture fisiche lob 0, letture read lob 0.
(Per la seconda query, quella veloce)
Tabella "PTable". Conteggio scansioni 1, letture logiche 4, letture fisiche 0, letture avanti 0, letture logiche lob 0, letture fisiche lob 0, letture read lob 0.
Nota l'enorme differenza nelle letture logiche. L'indice viene utilizzato in entrambi i casi.
La frammentazione dell'indice potrebbe spiegare un po ', ma credo che l'impatto sia molto piccolo; e il problema non si è mai verificato prima. Un'altra prova è se eseguo una query come:
select * from EventLog with (nolock) where EventID=xxxx
Anche se imposto xxxx sugli EventID più piccoli nella tabella, la query è sempre velocissima.
Abbiamo verificato e non vi sono problemi di blocco / blocco.
Nota: ho appena provato a semplificare il problema sopra. Il "PTable" è in realtà "EventLog"; l' PID
è EventID
.
Ottengo lo stesso risultato test senza il NOLOCK
suggerimento.
Qualcuno può aiutare?
Piani di esecuzione delle query più dettagliati in XML come segue:
https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob
https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ
Non credo sia importante fornire l'istruzione create table. È un vecchio database e funziona perfettamente da molto tempo fino alla manutenzione. Abbiamo fatto molte ricerche da soli e le abbiamo ristrette alle informazioni fornite nella mia domanda.
La tabella è stata creata normalmente con la EventID
colonna come chiave primaria, che è una identity
colonna di tipo bigint
. In questo momento, immagino che il problema sia con la frammentazione dell'indice. Subito dopo la ricostruzione dell'indice, il problema sembrava essere scomparso per mezza giornata; ma perché è tornato così in fretta ...?