Skip to content

Execution DMVs

A collection of queries covering the execution DMVs: query stats, cached plans and plan attributes for finding and analyzing queries.

Published Dec 15, 2006

Which queries are in the cache, and how expensive are they? This collection covers sys.dm_exec_query_stats, sys.dm_exec_cached_plans and sys.dm_exec_plan_attributes. The first two queries find every cached instance matching a piece of text; the plan-attributes query exposes what SQL Server knows about each cached plan; the plan-cache summary reports how much memory each cache object type is holding - including how much of it has only ever been used once (prime candidates for eviction); the next one gives per-statement execution counts with average physical/logical reads, writes, CLR time and elapsed time for the last two hours; and the final query ranks statements by average CPU time using query hashes.

/*
sys.dm_exec_query_stats
sys.dm_exec_cached_plans
sys.dm_exec_plan_attributes
*/



-------------------------------
-- dm_exec_query_stats
--
-- Find all instances based on query text from dm_exec_query_stats
-------------------------------  
select * 
from sys.dm_exec_query_stats
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
where text like '%select * from Person.Address%'


-------------------------------
-- dm_exec_cached_plans
--
-- Find all instances based on query text from dm_exec_cached_plans - tip 1661
-------------------------------  
SELECT usecounts, cacheobjtype, objtype, text, query_plan, ISNULL(DB_NAME(dm_exec_sql_text.dbid),'ResourceDB') AS DatabaseName
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) 
where text like '%select * from Person.Address%'
ORDER BY usecounts DESC;


-------------------------------
-- dm_exec_plan_attributes
--
-- Query stats and plan attributes - tip 1829
-------------------------------
SELECT SDEQP.query_plan, SDEPA.attribute, SDEPA.value, *
FROM sys.dm_exec_cached_plans SDECP 
   INNER JOIN sys.dm_exec_requests SDER ON SDECP.plan_handle = SDER.plan_handle 
   INNER JOIN sys.dm_exec_sessions SDES ON SDER.session_id = SDES.session_id 
   CROSS APPLY sys.dm_exec_query_plan(SDECP.plan_handle) AS SDEQP 
   CROSS APPLY sys.dm_exec_plan_attributes(SDECP.plan_handle) AS SDEPA 

   
-------------------------------
-- Query stats and plan cache - tip 2527
-------------------------------
WITH CACHE_ALLOC AS
(
SELECT  objtype AS [CacheType]
        ,COUNT_BIG(objtype) AS [Total Plans]
        , sum(cast(size_in_bytes as decimal(18,2)))/1024/1024 AS [Total MBs]
        , avg(usecounts) AS [Avg Use Count]
        , sum(cast((CASE WHEN usecounts = 1 THEN size_in_bytes ELSE 0 END) as decimal(18,2)))/1024/1024 AS [Total MBs - USE Count 1]
        , CASE 
      WHEN (Grouping(objtype)=1) THEN count_big(objtype)
      ELSE 0 
      END AS GTOTAL
          FROM sys.dm_exec_cached_plans
GROUP BY objtype 
) 
   SELECT
      [CacheType], [Total Plans],[Total MBs],
      [Avg Use Count],[Total MBs - USE Count 1],
      Cast([Total Plans]*1.0/Sum([Total Plans])OVER() * 100.0 AS DECIMAL(5, 2)) As Cache_Alloc_Pct
      FROM CACHE_ALLOC
      Order by [Total Plans] desc



-------------------------------
-- Query stats and plan cache - tip 1843
-------------------------------
SELECT  
       sdest.dbid  
       ,sdest.[text] AS Batch_Object, 
       SUBSTRING(sdest.[text], (sdeqs.statement_start_offset/2) + 1, 
       ((CASE sdeqs.statement_end_offset 
               WHEN -1 THEN DATALENGTH(sdest.[text]) ELSE sdeqs.statement_end_offset END 
                       - sdeqs.statement_start_offset)/2) + 1) AS SQL_Statement 
       , sdeqp.query_plan  
       , sdeqs.execution_count 
       , sdeqs.total_physical_reads 
       ,(sdeqs.total_physical_reads / sdeqs.execution_count) AS average_physical_reads 
       , sdeqs.total_logical_writes 
       , (sdeqs.total_logical_writes / sdeqs.execution_count) AS average_logical_writes 
       , sdeqs.total_logical_reads 
       , (sdeqs.total_logical_reads / sdeqs.execution_count) AS average_logical_lReads 
       , sdeqs.total_clr_time 
       , (sdeqs.total_clr_time / sdeqs.execution_count) AS average_CLRTime 
       , sdeqs.total_elapsed_time 
       , (sdeqs.total_elapsed_time / sdeqs.execution_count) AS average_elapsed_time 
       , sdeqs.last_execution_time 
       , sdeqs.creation_time  
FROM sys.dm_exec_query_stats AS sdeqs 
       CROSS apply sys.dm_exec_sql_text(sdeqs.sql_handle) AS sdest 
       CROSS apply sys.dm_exec_query_plan(sdeqs.plan_handle) AS sdeqp 
WHERE  sdeqs.last_execution_time > DATEADD(HH,-2,GETDATE())  
               --AND sdest.dbid = (SELECT DB_ID('AdventureWorks')) 
ORDER BY execution_count DESC  


-------------------------------
-- Query stats by avg cpu time
-------------------------------   
SELECT TOP 5 query_stats.query_hash AS "Query Hash", 
    SUM(query_stats.total_worker_time) / SUM(query_stats.execution_count) AS "Avg CPU Time",
    MIN(query_stats.statement_text) AS "Statement Text"
FROM 
    (SELECT QS.*, 
    SUBSTRING(ST.text, (QS.statement_start_offset/2) + 1,
    ((CASE statement_end_offset 
        WHEN -1 THEN DATALENGTH(st.text)
        ELSE QS.statement_end_offset END 
            - QS.statement_start_offset)/2) + 1) AS statement_text
     FROM sys.dm_exec_query_stats AS QS
     CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle) as ST) as query_stats
GROUP BY query_stats.query_hash
ORDER BY 2 DESC;
An unhandled error has occurred. Reload 🗙