Potrebbe accadere che una piccola quantità di dati raggiunga un certo limite in SQL Server per forzare un altro piano o qualcosa del genere. Questo non è improbabile. Ma il fatto che il tuo disco sembri essere pesantemente sotto servizio mi porta a un'altra conclusione.
Ci sono 2 possibili motivi di base per il tuo rallentamento.
- Hai aggiornato il tuo sistema e riavviato
- Si carica un mucchio di dati in esso
Diamo un'occhiata alla parte n. 1
È possibile che la configurazione di SQL Server sia stata interrotta. Ciò può causare seri problemi relativi alla velocità del server e all'utilizzo del disco.
Verifica in prima istanza le impostazioni di base del server. Queste impostazioni di base sono max server memory
, affinity I/O mask
, affinity mask
e max degree of parallelism
. Potrebbe essere necessario abilitare le opzioni avanzate utilizzando show advanced options
.
Ecco uno script completo:
-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'
Confronta il risultato con i valori documentati nei passaggi dell'installazione. Sono sempre gli stessi?
Potrebbe avere molte ragioni per cui il tuo server si comporta in modo strano. Scommetto normalmente che il tuo max server memory
è semplicemente sbagliato. Ciò causerà lo scambio permanente delle pagine di dati in SQL Server. Non può contenere tutto nella sua memoria. Ciò significa che deve leggere le pagine dal disco, aggiornarlo, riscriverlo all'istante. Se arriva un altro aggiornamento e utilizza la stessa pagina per un aggiornamento, non può essere letto dalla memoria. Al contrario, il server deve rileggerlo dal disco. Sto solo scambiando ...
Un altro problema può essere un'alta affinità su disco o processi. Se hai utilizzato un server condiviso (SQL Server + altri servizi) con un disco dedicato per SQL Server (che può essere un caso raro, ma potrebbe essere), questo potrebbe essere il tuo problema. Il server normalmente utilizzava, ad esempio, 3 cpus per i processi e uno per l'I / O. Gli altri 12 cpus sono utilizzati per altri servizi. In questo caso la maschera di affinità è errata e utilizza ad esempio una configurazione automatica. Ciò significa che il server utilizza tutti i 16 core per processi e I / O in modo dinamico. Se hai processi enormi in esecuzione, possono caricare un carico enorme sul disco, che potrebbe non essere in grado di gestire. Ma in realtà, non credo che questo sia il tuo caso. Sarebbe più veloce (anche se solo un po ') se questo si applica, ma il tuo caso è un rallentamento.
Un altro problema potrebbe essere un grado troppo elevato di parallelismo. Ciò significa che hai troppi thread inattivi su un parziale di una query. Ciò potrebbe anche causare un enorme rallentamento se il parallelismo non funziona come previsto. Ma questo non descriverà il tuo I / O elevato in totale.
Ora diamo un'occhiata anche alla parte n. 2
Carichi un mucchio di righe nel tuo sistema. Anche se si tratta di un lavoro regolare, potrebbe sollevare un limite in cui i piani di query aumentano. È possibile che l'inserimento in combinazione con SQL Server produca questo comportamento.
Hai detto che hai già provato a migrare i tuoi indici su un altro disco, il che sembra aiutare. Questo può essere successo solo per il fatto che hai diviso il carico su due dischi diversi.
È possibile che i tuoi indici siano stati fratturati, che i tuoi piani siano stati fratturati o che le tue statistiche siano appena obsolete.
1. consente di controllare l'ultimo aggiornamento delle statistiche
È possibile farlo manualmente tramite l'interfaccia per ogni singolo elemento statistico. Quale sarebbe un dolore. Oppure puoi provare questo codice:
SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
Questo ti darà informazioni complete su ogni indice (e heap) e le statistiche dietro di essi. Anche se eseguito sp_updatestats
, ciò non significa che le statistiche siano state aggiornate. La parte in cui un aggiornamento è piuttosto complicata, anche se si esegue sp_updatestats
o anche se auto update statistics
è abilitata, le statistiche non verranno aggiornate appena in tempo. Ecco alcuni spunti, quando è necessario / generato un aggiornamento:
- Una tabella vuota ottiene una o più righe
- Una tabella con più di 500 righe aggiorna il 20% + 500 righe aggiuntive e successivamente è stato inserito un inserto
- Quando sono state modificate 500 righe in una tabella che contiene meno di 500 righe
Ciò significa che le tue statistiche potrebbero essere obsolete anche se esegui l'aggiornamento.
Puoi dare un'occhiata alla query sopra. Se trovi alcune statistiche piuttosto vecchie in alcune tabelle, potresti voler eseguire un aggiornamento statistico manuale per questa tabella:
UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN
Dopodiché, potresti voler dare un calcio al culo al tuo server per buttare via tutti i vecchi piani.
DBCC FREEPROCCACHE
Se vuoi solo pulire tutte le cache, potresti invece eseguire questo:
DBCC FREESYSTEMCACHE ('ALL')
Questo pulirà tutte le cache, non solo la cache del piano. Normalmente avviserei di usarlo su un server di produzione in fase di produzione. Ma poiché il tuo server non funziona attualmente, non puoi danneggiarli troppo. Potrebbe rallentare per alcuni secondi forse 1-2 minuti in quanto ha bisogno di ricostruire tutte le cache, ma dopo dovrebbe eseguire i piani corretti.
Un altro motivo possono essere indici totalmente frammentati. Questo può essere verificato su tutto il server usando questa istruzione:
SELECT *
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)
Se la frammentazione è molto elevata, potrebbe essere necessario riorganizzarla (frammentazione <20%) o ricostruirla completamente (> 20%). Ciò potrebbe richiedere una maggiore pressione sul disco e causare problemi. D'altra parte, se gli indici sono così negativi, probabilmente aiuterebbe alla fine più di quanto faccia male.
Oltre a questi due motivi, potrebbe esserci ancora un terzo problema
Forse il tuo server è probabilmente configurato, non hai modificato alcun codice in questo momento, hai appena aggiunto alcune righe. Tutte le statistiche vengono aggiornate e tutte le cache vengono ricostruite. Tutti i tuoi indici sono riorganizzati nel modo in cui ne hai bisogno, ma comunque non funziona nulla. È possibile che tu abbia raggiunto il limite di memoria disponibile nei tuoi processi. Forse hai bisogno di più. Puoi semplicemente verificare se esiste un processo che tenta di ottenere più memoria di quella che hai.
Puoi verificarlo usando questo comando:
SELECT * FROM sys.dm_exec_query_memory_grants
Ti fornirà un elenco di tutte le sessioni che consumano memoria. Potrebbe esserci qualche query che è ancora in attesa di ottenere memoria. Queste query possono essere facilmente filtrate. Tutte le sessioni dove granted_memory_kb IS NULL
. Queste sono sessioni che richiedono memoria ma non la ottengono. Un'altra cosa può essere una memoria garantita che potrebbe essere troppo bassa. Puoi confrontare le colonne requested_memory_kb
con granted_memory_kb
. Richiesto mostra la quantità di memoria necessaria per l'esecuzione ottimale del processo mentre concesso mostra la memoria abilitata per il processo. Se un processo ha bisogno di 2 GB per essere eseguito ma ottiene solo 2 MB ... potresti averlo da solo. ;-)
Un altro modo è controllare RESSOURCE_SEMAPHORE
:
SELECT * FROM sys.dm_exec_query_resource_semaphore
Puoi dare un'occhiata al waiter_count
e al grantee_count
. Se il cameriere è superiore a 0, hai una pressione nella memoria, che può causare lo scambio e la pressione del disco vista da te nel perfmon.