Pregunta

¿Es posible obtener un desglose de la utilización de la CPU? por base de datos?

Idealmente estoy buscando una interfaz tipo Administrador de tareas para el servidor SQL, pero en lugar de mirar la utilización de la CPU de cada PID (como taskmgr) o cada SPID (como spwho2k5), quiero ver la utilización total de CPU de cada base de datos.Suponga una única instancia de SQL.

Me doy cuenta de que se podrían escribir herramientas para recopilar estos datos e informar sobre ellos, pero me pregunto si existe alguna herramienta que me permita ver en vivo qué bases de datos contribuyen más al sqlservr.exe Carga de CPU.

¿Fue útil?

Solución

Algo así como.Mira esta consulta:

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

Esto le proporcionará las consultas en la caché del plan en orden de cuánta CPU han consumido.Puede ejecutar esto periódicamente, como en un trabajo del Agente SQL, e insertar los resultados en una tabla para asegurarse de que los datos persistan más allá de los reinicios.

Cuando lea los resultados, probablemente se dará cuenta de por qué no podemos correlacionar esos datos directamente con una base de datos individual.En primer lugar, una única consulta también puede ocultar su verdadera base de datos principal mediante trucos como este:

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

La consulta se ejecutaría en MSDB, pero sondearía los resultados de AdventureWorks.¿Dónde debemos asignar el consumo de CPU?

Empeora cuando:

  • Unir entre múltiples bases de datos
  • Ejecute una transacción en varias bases de datos y el esfuerzo de bloqueo abarcará varias bases de datos.
  • Ejecute trabajos del Agente SQL en MSDB que "funcionan" en MSDB, pero realizan copias de seguridad de bases de datos individuales

Lo sigue y sigue.Por eso tiene sentido ajustar el rendimiento a nivel de consulta en lugar de a nivel de base de datos.

En SQL Server 2008R2, Microsoft introdujo funciones de gestión del rendimiento y de aplicaciones que nos permitirán empaquetar una única base de datos en un paquete DAC distribuible e implementable, y son características prometedoras para facilitar la gestión del rendimiento de bases de datos individuales y sus aplicaciones.Sin embargo, todavía no hace lo que estás buscando.

Para más de ellos, consulte el Repositorio T-SQL en la wiki de SQL Server de Toad World (anteriormente en SQLServerPedia).

Actualizado el 29 de enero para incluir números totales en lugar de solo promedios.

Otros consejos

SQL Server (a partir de 2000) instalará contadores de rendimiento (visibles desde Performance Monitor o Perfmon).

Una de las categorías de contador (de una instalación de SQL Server 2005 es :) - SQLServer: bases de datos

Con una instancia para cada base de datos.Sin embargo, los contadores disponibles no proporcionan un contador de % de utilización de CPU o algo similar, aunque hay algunos contadores de velocidad que puede utilizar para obtener una buena estimación de la CPU.El ejemplo sería, si tiene 2 bases de datos y la tasa medida es de 20 transacciones/seg en la base de datos A y 80 transacciones/seg en la base de datos B, entonces sabría que A contribuye aproximadamente al 20% de la CPU total, y B contribuye con el otro 80%.

Hay algunas fallas aquí, ya que se supone que todo el trabajo que se realiza está vinculado a la CPU, lo que por supuesto no ocurre con las bases de datos.Pero creo que eso sería un comienzo.

Aquí hay una consulta que mostrará la base de datos real que causa una carga alta.Se basa en la caché de consultas, que puede vaciarse con frecuencia en escenarios con poca memoria (lo que hace que la consulta sea menos útil).

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

Creo que la respuesta a tu pregunta es no.

El problema es que una actividad en una máquina puede provocar una carga en varias bases de datos.Si tengo un proceso que lee desde una base de datos de configuración, inicia sesión en una base de datos de registro y mueve transacciones dentro y fuera de varias bases de datos según el tipo, ¿cómo particiono el uso de la CPU?

Podría dividir la utilización de la CPU por la carga de transacciones, pero esa es nuevamente una métrica aproximada que puede engañarlo.¿Cómo dividiría el envío de registros de transacciones de una base de datos a otra, por ejemplo?¿La carga de la CPU está en lectura o escritura?

Es mejor observar la tasa de transacción de una máquina y la carga de CPU que provoca.También puede perfilar los procedimientos almacenados y ver si alguno de ellos está tomando una cantidad excesiva de tiempo;sin embargo, esto no le dará la respuesta que desea.

Teniendo en cuenta todo lo dicho anteriormente.
A partir de SQL Server 2012 (¿puede ser 2008?), hay una columna id_base de datos en sys.dm_exec_sessions.
Nos proporciona un cálculo sencillo de la CPU para cada base de datos para actualmente conectado sesiones.Si la sesión se desconectó, entonces sus resultados desaparecieron.

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;

Echa un vistazo a Centinela SQL.Hace todo lo que necesitas y más.

Saludos, Lieven

¿Has mirado el generador de perfiles SQL?

Tome la plantilla estándar "T-SQL" o "Procedimiento almacenado", modifique los campos para agruparlos por ID de la base de datos (creo que debe usar el número, no obtiene el nombre de la base de datos, pero es fácil de descubrir usando exec sp_databases para obtener la lista)

Ejecute esto por un tiempo y obtendrá los recuentos totales de CPU/Disco IO/Espera, etc.Esto puede brindarle la proporción de CPU utilizada por cada base de datos.

Si monitorea el contador PerfMon al mismo tiempo (registra los datos en una base de datos SQL) y hace lo mismo para SQL Profiler (registra los datos en la base de datos), puede ser capaz de correlacionar los dos juntos.

Aun así, debería darle una pista suficiente sobre qué base de datos vale la pena analizar con más detalle.Luego, haga lo mismo nuevamente con solo esa ID de base de datos y busque los procedimientos almacenados/SQL más caros.

por favor revisa esta consulta:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top