Domanda

È possibile ottenere una ripartizione dell'utilizzo della CPU per banca dati?

Idealmente sto cercando un'interfaccia di tipo Task Manager per il server SQL, ma invece di guardare l'utilizzo della CPU di ciascun PID (come taskmgr) o ogni SPID (come spwho2k5), desidero visualizzare l'utilizzo totale della CPU di ciascun database.Supponiamo che vi sia una singola istanza SQL.

Mi rendo conto che si potrebbero scrivere strumenti per raccogliere questi dati e riferirli, ma mi chiedo se esiste qualche strumento che mi consenta di vedere in tempo reale quali database contribuiscono maggiormente al sqlservr.exe Carico della CPU.

È stato utile?

Soluzione

Una specie di.Controlla questa query:

SELECT total_worker_time/execution_count AS AvgCPU  
, total_worker_time AS TotalCPU
, total_elapsed_time/execution_count AS AvgDuration  
, total_elapsed_time AS TotalDuration  
, (total_logical_reads+total_physical_reads)/execution_count AS AvgReads 
, (total_logical_reads+total_physical_reads) AS TotalReads
, execution_count   
, SUBSTRING(st.TEXT, (qs.statement_start_offset/2)+1  
, ((CASE qs.statement_end_offset  WHEN -1 THEN datalength(st.TEXT)  
ELSE qs.statement_end_offset  
END - qs.statement_start_offset)/2) + 1) AS txt  
, 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 1 DESC

In questo modo riceverai le query nella cache del piano in ordine di quantità di CPU utilizzata.È possibile eseguirlo periodicamente, come in un processo di SQL Agent, e inserire i risultati in una tabella per assicurarsi che i dati persistano oltre i riavvii.

Quando leggerai i risultati, probabilmente capirai perché non possiamo correlare i dati direttamente a un singolo database.Innanzitutto, una singola query può anche nascondere il suo vero genitore del database eseguendo trucchi come questi:

USE msdb
DECLARE @StringToExecute VARCHAR(1000)
SET @StringToExecute = 'SELECT * FROM AdventureWorks.dbo.ErrorLog'
EXEC @StringToExecute

La query verrebbe eseguita in MSDB, ma effettuerebbe il polling dei risultati da AdventureWorks.Dove dovremmo assegnare il consumo della CPU?

La situazione peggiora quando:

  • Partecipa tra più database
  • Esegui una transazione in più database e lo sforzo di blocco si estende su più database
  • Esegui processi di SQL Agent in MSDB che "funzionano" in MSDB, ma esegui il backup dei singoli database

Va avanti all'infinito.Ecco perché ha senso ottimizzare le prestazioni a livello di query anziché a livello di database.

In SQL Server 2008R2, Microsoft ha introdotto funzionalità di gestione delle prestazioni e di gestione delle app che ci consentiranno di impacchettare un singolo database in un pacchetto DAC distribuibile e distribuibile e promettono funzionalità per semplificare la gestione delle prestazioni dei singoli database e delle loro applicazioni.Tuttavia, continua a non fare quello che stai cercando.

Per saperne di più, dai un'occhiata a Repository T-SQL sul wiki di SQL Server di Toad World (precedentemente su SQLServerPedia).

Aggiornato il 29/01 per includere i numeri totali anziché solo le medie.

Altri suggerimenti

SQL Server (a partire dalla versione 2000) installerà i contatori delle prestazioni (visualizzabili da Performance Monitor o Perfmon).

Una delle categorie di contatore (da un'installazione SQL Server 2005 è :) - SQLServer: database

Con un'istanza per ciascun database.I contatori disponibili tuttavia non forniscono un contatore della percentuale di utilizzo della CPU o qualcosa di simile, sebbene siano presenti alcuni contatori della velocità che è possibile utilizzare per ottenere una buona stima della CPU.Ad esempio, se disponi di 2 database e la velocità misurata è 20 transazioni/sec sul database A e 80 transazioni/sec sul database B --- allora sapresti che A contribuisce all'incirca al 20% della CPU totale e B contribuisce al restante 80%.

Ci sono alcuni difetti qui, poiché ciò presuppone che tutto il lavoro svolto sia legato alla CPU, cosa che ovviamente con i database non lo è.Ma sarebbe un inizio, credo.

Ecco una query che mostrerà il database effettivo che causa un carico elevato.Si basa sulla cache delle query che potrebbe essere svuotata frequentemente in scenari con memoria insufficiente (rendendo la query meno utile).

select dbs.name, cacheobjtype, total_cpu_time, total_execution_count from
    (select top 10
        sum(qs.total_worker_time) as total_cpu_time,  
        sum(qs.execution_count) as total_execution_count, 
        count(*) as  number_of_statements,  
        qs.plan_handle
    from  
        sys.dm_exec_query_stats qs 
    group by qs.plan_handle
    order by sum(qs.total_worker_time) desc
    ) a
inner join 
(SELECT plan_handle, pvt.dbid, cacheobjtype
FROM (
    SELECT plan_handle, epa.attribute, epa.value, cacheobjtype
    FROM sys.dm_exec_cached_plans 
        OUTER APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
     /* WHERE cacheobjtype = 'Compiled Plan' AND objtype = 'adhoc' */) AS ecpa 
PIVOT (MAX(ecpa.value) FOR ecpa.attribute IN ("dbid", "sql_handle")) AS pvt
) b on a.plan_handle = b.plan_handle
inner join sys.databases dbs on dbid = dbs.database_id

Penso che la risposta alla tua domanda sia no.

Il problema è che un'attività su una macchina può causare un carico su più database.Se ho un processo che legge da un DB di configurazione, accede a un DB di registrazione e sposta transazioni dentro e fuori da vari DB in base al tipo, come posso partizionare l'utilizzo della CPU?

Potresti dividere l'utilizzo della CPU per il carico della transazione, ma anche questa è una metrica approssimativa che potrebbe fuorviarti.Ad esempio, come divideresti la spedizione dei log delle transazioni da un DB a un altro?Il carico della CPU è in lettura o in scrittura?

Faresti meglio a considerare il tasso di transazione per una macchina e il carico della CPU che provoca.È inoltre possibile profilare le procedure memorizzate e vedere se qualcuna di esse impiega una quantità eccessiva di tempo;tuttavia, questo non ti darà la risposta desiderata.

Tenendo presente tutto quanto detto sopra.
A partire da SQL Server 2012 (potrebbe essere il 2008?), è presente la colonna id_database In sys.dm_exec_sessions.
Ci fornisce un facile calcolo della CPU per ciascun database attualmente connesso sessioni.Se la sessione si è disconnessa, i suoi risultati sono scomparsi.

select session_id, cpu_time, program_name, login_name, database_id 
  from sys.dm_exec_sessions 
 where session_id > 50;

select sum(cpu_time)/1000 as cpu_seconds, database_id 
 from sys.dm_exec_sessions 
group by database_id
order by cpu_seconds desc;

Dare un'occhiata a Sentinella SQL.Fa tutto ciò di cui hai bisogno e altro ancora.

Saluti, Lieven

Hai dato un'occhiata al profiler SQL?

Prendi il modello standard "T-SQL" o "Stored Procedure", modifica i campi da raggruppare in base all'ID del database (penso che devi usare il numero, non ottieni il nome del database, ma è facile scoprirlo usando exec sp_databases per ottenere l'elenco)

Eseguilo per un po' e otterrai il numero totale di CPU/IO disco/Attesa ecc.Questo può darti la percentuale di CPU utilizzata da ciascun database.

Se monitori contemporaneamente il contatore PerfMon (registra i dati in un database SQL) e fai lo stesso per SQL Profiler (registra i dati nel database), puoi Maggio essere in grado di correlare i due insieme.

Anche così, dovrebbe darti un indizio sufficiente su quale DB vale la pena esaminare in modo più dettagliato.Quindi, fai di nuovo la stessa cosa solo con quell'ID del database e cerca le procedure SQL/stored più costose.

per favore controlla questa query:

SELECT 
    DB_NAME(st.dbid) AS DatabaseName
    ,OBJECT_SCHEMA_NAME(st.objectid,dbid) AS SchemaName
    ,cp.objtype AS ObjectType
    ,OBJECT_NAME(st.objectid,dbid) AS Objects
    ,MAX(cp.usecounts)AS Total_Execution_count
    ,SUM(qs.total_worker_time) AS Total_CPU_Time
    ,SUM(qs.total_worker_time) / (max(cp.usecounts) * 1.0) AS Avg_CPU_Time 
FROM sys.dm_exec_cached_plans cp 
INNER JOIN sys.dm_exec_query_stats qs 
    ON cp.plan_handle = qs.plan_handle
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
WHERE DB_NAME(st.dbid) IS NOT NULL
GROUP BY DB_NAME(st.dbid),OBJECT_SCHEMA_NAME(objectid,st.dbid),cp.objtype,OBJECT_NAME(objectid,st.dbid) 
ORDER BY sum(qs.total_worker_time) desc
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top