Elevato utilizzo della CPU su server SQL - Query lente [chiuso]


11

Il nostro MS SQL Server utilizza circa il 95% della potenza della CPU.

Dopo un riavvio del server (hardware) o un riavvio del servizio SQL, l'utilizzo è pari allo 0% e aumenta lentamente nel corso di 1-3 giorni. A seconda di quanto viene utilizzato.

Quando supera l'80%, ogni query è estremamente lenta.

Il nostro sito web si occupa di molte query di grandi dimensioni, quindi alcune di esse richiedono 45-60 secondi. Dopo un riavvio (utilizzo della CPU inferiore all'80%), sono necessari 11-20 secondi per la stessa query.


Come posso risolvere questo problema? Ho letto online che le maschere di affinità possono regolare l'utilizzo della CPU, ma le impostazioni di Affinity sono disabilitate. Non posso cambiarli. Questo perché ho solo 1 processore?

Ci sono molti trucchi da fare con le query stesse, ma i nostri siti Web e servizi sono piuttosto grandi e c'è semplicemente troppo da cambiare.

Molti di loro sono già abbastanza ottimizzati.


Non riesco a continuare a riavviare il servizio SQL, anche se ci vogliono solo 2 secondi, perché abbiamo un servizio di allarme che consente alle persone di chiamare e registrare un messaggio, un gruppo selezionato verrà quindi chiamato e ascoltare il messaggio registrato.

Questo sistema viene utilizzato da centinaia di team di ricerca e salvataggio e, se il servizio SQL si riavvia durante un allarme, verrà chiuso e la persona che lo ha chiamato non verrà informata.


Ho cercato dappertutto, ma non ho trovato nulla tranne le cose su "Maschere di affinità", che non posso cambiare.

Ci deve essere un modo per svuotare la cache della CPU, senza terminare le query correnti ... giusto?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White 9

Risposte:


7

Questo è un colpo lungo, ma potresti voler dare un'occhiata alle tue impostazioni di parametrizzazione forzata. Se si riscontra un gran numero di piani di query quando le prestazioni sono scadenti, le query non vengono memorizzate nella cache nel modo previsto e le query impiegano molto tempo a eseguire la scansione della cache per vedere se esiste già un piano. Se la cancellazione della cache risolve questo problema, potresti voler esaminare la modifica dell'impostazione della parametrizzazione forzata. Puoi cancellare la cache usando:

DBCC FREEPROCCACHE

È possibile verificare quale sia l'impostazione di parametrizzazione forzata se si cancella la cache ha funzionato:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Questo è probabilmente impostato su 0, il valore predefinito. Se lo desiderano, puoi impostarlo su true facendo:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Questo dovrebbe essere fatto prima in un ambiente di sviluppo e vedere se questo ha un impatto negativo sul database in altri modi. Può essere ripristinato usando:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;

5
Notare che liberare la cache delle procedure potrebbe effettivamente causare un enorme picco nella CPU, poiché tutte le query dovranno ora ricompilare i loro piani di esecuzione.
Aaron Bertrand

18

Affinity non "regola l'utilizzo della CPU" (ad esempio, nel caso in cui le CPU eseguano meno lavoro), consente di spegnere una CPU (forse per renderla disponibile a un'altra istanza sulla stessa macchina) o impostare una CPU su aiuto solo con I / O. Anche se avessi più CPU, non saresti in grado di utilizzare il primo per aiutarti con il tuo obiettivo, ed è impossibile per noi indovinare il secondo perché non sappiamo cosa sta guidando l'utilizzo della tua CPU così in alto. Potrebbe essere dovuto a indicizzazione estremamente scadente, compilazioni eccessive, abbondanza di UDF scalari, thrashing I / O, chi lo sa? (E la ragione per cui l'I / O potrebbe essere la causa è che se il tuo database è più grande di circa 3 GB, dovrà costantemente scambiare dati dentro e fuori dalla memoria del pool di buffer, e questo avrà un impatto sulla CPU.)

La cache della CPU, inoltre, è una tana di coniglio che non è necessario scendere. Dubito fortemente che la tua CPU stia crollando al 95% a causa di problemi con la cache della CPU.

Per limitare la fonte della pressione della CPU e supponendo che tu stia utilizzando le procedure memorizzate, puoi dare un'occhiata a questa query diagnostica da Glenn Berry ( proveniente da qui ) - assicurati di eseguirla nel contesto del database giusto:

-- Top Cached SPs By Total Worker time (SQL Server 2012). 
-- Worker time relates to CPU cost  (Query 44) (SP Worker Time)

SELECT TOP (25) 
  p.name AS [SP Name], 
  qs.total_worker_time AS [TotalWorkerTime], 
  qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], 
  qs.execution_count, 
  ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) 
    AS [Calls/Second],
  qs.total_elapsed_time, 
  qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time], 
  qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

-- This helps you find the most expensive cached stored procedures from a CPU perspective
-- You should look at this if you see signs of CPU pressure

Se non si utilizzano procedure memorizzate, questo esempio di John Samson può aiutare a isolare le query ad hoc ( provenienti da qui ):

SELECT TOP (25)
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
    qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
    (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
    qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS apply sys.dm_exec_query_plan (qs.plan_handle) AS qp
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

Puoi anche dare un'occhiata a sp_WhoIsActive di Adam Machanic , una procedura memorizzata che può analizzare rapidamente tutte le query attualmente in esecuzione e consentirti di ordinarle come preferisci (ad esempio nel tuo caso @sort_order = '[CPU] DESC').

La prima cosa che farei, anche se in particolare se questo è veramente fondamentale per le squadre di ricerca e salvataggio, è acquistare hardware migliore. Dovresti avere più CPU e più RAM per servire la tua applicazione. È inoltre assolutamente necessaria una migliore disponibilità elevata (ad esempio clustering, mirroring o gruppi di disponibilità). Non vi è alcun motivo per cui un riavvio di una macchina fisica debba portare la tua applicazione completamente offline - abbiamo soluzioni migliori per questo problema. E infine, presumo che questo "server" abbia solo un disco rigido. Ciò significa che tutto l'I / O - dal sistema operativo, dai file di dati di SQL Server, dai file di registro, dal tempdb, ecc., Passa attraverso un singolo controller e condivide l'attività di lettura / scrittura su una singola unità. Ottieni più dischi. Ottieni SSD se / dove puoi. Utilizzare RAID e provare a distribuire l'I / O il più possibile.

Detto questo, lanciare l'hardware al problema non sarà l'unica parte della correzione. È necessario isolare esattamente cosa sta causando un uso eccessivo della CPU e quindi attaccare tali problemi, indipendentemente dall'hardware in uso.

Vedi anche questa domanda StackOverflow per alcune altre idee:

/programming/945063/how-do-i-find-out-what-is-hammering-my-sql-server


0

I seguenti suggerimenti sono uno "scatto al buio" perché non riesco a vedere il codice reale.

Il primo è che un SP potrebbe aprire i cursori e lasciarli aperti. Leggi su Cursori, in particolare Chiudi e Deallocate. Qualcuno potrebbe chiudere, ma non deallocare i cursori. Il comportamento potrebbe essere cambiato a causa dell'aggiornamento, il 2012 potrebbe trattare i cursori rimanenti in modo diverso dal 2008 R2.

Il secondo è che potrebbero esserci blocchi della tabella che non vengono cancellati. Ancora una volta, sono a distanza, quindi non posso dirlo, ma suggerirebbe che qualcuno crei una tabella temporanea globale dopo una "transazione iniziale" e che non venga eseguita alcuna "transazione finale" o che la procedura memorizzata non riesca a lasciare un blocco tabella che occupa spazio in tempdb.

Stai usando WinLink per caso? Qualcosa su questo sembra vagamente familiare.


-4

È necessario disporre di un meccanismo di memorizzazione nella cache come memcached per migliorare le prestazioni


Ma questo non cambierebbe l'utilizzo della CPU su SQL Server, giusto? Renderebbe le query più veloci sul sito Web e potrebbero esserci problemi se qualcosa viene cambiato in una tabella mentre qualcun altro sta utilizzando i risultati memorizzati nella stessa tabella, giusto?
Levi Johansen,

@Levi se si memorizzano nella cache i risultati della query da qualche parte nel livello intermedio, le query non raggiungono il database (tranne quando è necessario aggiornare la cache).
Aaron Bertrand

1
Se anche la CPU è alta quando nessuno si trova sul sito Web, ovviamente la memorizzazione nella cache di roba a livello Web non sarebbe di aiuto. Memcached è un ottimo strumento, ma non un sostituto per una persona competente per sedersi e scoprire cosa sta facendo il server quando presumibilmente non dovrebbe fare nulla.
TomTom,
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.