DBCC命令不能分析存储过程的“执行计划碎片”,因该概念不存在;执行计划缓存在内存中,不产生页级或区级碎片,DBCC SHOWCONTIG仅支持表、视图或索引名,传入存储过程名将报错。

DBCC 命令不能分析存储过程的“执行计划碎片”——因为根本不存在这种东西。
执行计划本身不产生碎片;SQL Server 缓存的是编译后的执行计划(存于 sys.dm_exec_query_plan 和计划缓存中),它不占用数据页、不涉及页链、不产生逻辑/区碎片。所谓“执行计划碎片”是常见误解,混淆了索引碎片和计划缓存状态。
真正可能被误称为“执行计划碎片”的,通常指以下两类问题,但都和 DBCC 无关:
1. 计划缓存污染或低效重用
- 表现:同一存储过程反复编译(sys.dm_exec_cached_plans 中出现大量相似但 plan_handle 不同的条目)
- 原因:参数嗅探、未使用 sp_executesql、WITH RECOMPILE、数据库兼容级别切换等
- 检查方式:SELECT * FROM sys.dm_exec_cached_plans WHERE objtype = 'Proc',结合 sys.dm_exec_sql_text 和 sys.dm_exec_query_plan 分析重复/低效计划
- DBCC FREEPROCCACHE 可清空缓存,但这是“清理”而非“分析碎片”
2. 存储过程所依赖的表/索引存在严重碎片
- 这才是DBCC SHOWCONTIG 或更推荐的 sys.dm_db_index_physical_stats 的作用场景
- 碎片影响的是物理 I/O 效率,间接拖慢存储过程执行——但问题在数据层,不在执行计划本身
- 示例:若 usp_GetOrderDetail 查询 Orders 表的聚集索引,而该索引 avg_fragmentation_in_percent 达 70%,则扫描变慢
为什么 DBCC SHOWCONTIG 对存储过程无效?
-DBCC SHOWCONTIG 只接受表名、视图名或索引名作为参数,不接受存储过程名
- 尝试运行 DBCC SHOWCONTIG ('usp_GetOrderDetail') 会报错:Msg 15009, Level 16, State 1: Object 'usp_GetOrderDetail' does not exist in the database.
- 它底层依赖 OBJECT_ID(),而存储过程对象类型是 P,不是 U(用户表)或 IT(内部表)
该查什么?怎么查?
- 先定位存储过程读写的主表:SELECT DISTINCT referenced_entity_name FROM sys.dm_exec_describe_first_result_set(N'EXEC usp_GetOrderDetail 123', NULL, 0) 或解析其定义
- 再查这些表的索引碎片:
SELECT
OBJECT_NAME(object_id) AS table_name,
name AS index_name,
avg_fragmentation_in_percent,
page_count,
avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('Orders'), NULL, NULL, 'LIMITED')
WHERE index_id > 0;
- 若 avg_fragmentation_in_percent > 30%,考虑 ALTER INDEX ... REORGANIZE 或 REBUILD;若 ,无需处理
<p>真正容易被忽略的点:很多人花时间折腾“清理执行计划”,却放任核心表索引碎片长期高于 50%,结果优化毫无效果。碎片分析必须落到具体表和索引上,而不是过程名。</p>

















