sys.dm_exec_procedure_stats and sys.dm_exec_query_stats describe different cached-plan rows. Their reads, CPU, and duration values are useful for ranking work, but they are not a guaranteed accounting system whose totals always reconcile.
Last updated: November 10, 2026.
DECLARE @object_id int = OBJECT_ID(N'dbo.ProcessOrders');
SELECT plan_handle, cached_time, last_execution_time,
execution_count, total_logical_reads, total_worker_time
FROM sys.dm_exec_procedure_stats
WHERE database_id = DB_ID() AND object_id = @object_id;
SELECT qs.plan_handle, qs.creation_time, qs.last_execution_time,
qs.execution_count, qs.total_logical_reads, qs.total_worker_time,
SUBSTRING(st.text, qs.statement_start_offset / 2 + 1,
(CASE WHEN qs.statement_end_offset = -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
WHERE st.dbid = DB_ID() AND st.objectid = @object_id;Capture both result sets immediately, then compare plan_handle, creation time, and last execution time. Different lifetimes or multiple cached plans make a numeric sum misleading before statement text is even considered.
Understand the two cache scopes
Microsoft documents procedure statistics as one row per cached stored-procedure plan. The query statistics DMV returns one row per statement in a cached plan and updates only after a query finishes.
Recompilation, plan eviction, cache clearing, failover, and service restart can reset rows at different moments. Dynamic SQL can have a separate cache entry, and different session settings can create multiple plans for text that looks identical. A currently running statement is also absent from completed-query totals.
Use a coherent measurement window
Do not compare rows collected minutes apart on a busy server. Save a single snapshot with plan identifiers and timestamps, then repeat after a controlled workload. Group statement rows by the intended plan and include every matching cache entry. Treat missing rows as unknown history, not zero work.
For durable comparisons across cache turnover, use Query Store or an Extended Events session designed for the workload. DMVs remain excellent for finding expensive cached work, but differences between their aggregates do not by themselves prove a SQL Server 2019 regression or incorrect reads.