必须从执行计划缓存中反向匹配SQL文本并筛选含视图名的语句,因SQL Server不记录视图被访问动作;推荐JOIN sys.dm_exec_sql_text后用LIKE '%schema.view_name%'匹配,注意大小写、schema完整性和动态SQL限制。

不能靠查视图定义或系统视图直接看到“谁在调用”,必须从执行计划缓存里反向匹配 SQL 文本,再过滤出含视图名的语句。
用 sys.dm_exec_query_stats + query_plan 提取调用视图的查询
SQL Server 不记录“视图被访问”这一动作,只记录实际执行的查询语句。所以得从缓存的执行计划中,把那些 SELECT 语句里显式写了视图名的找出来。
- 必须先确保目标视图已被执行过至少一次,否则它不会出现在
sys.dm_exec_query_stats中 - 用
qp.query_plan.value('declare namespace p="http://schemas.microsoft.com/sqlserver/2004/07/showplan"; (//p:RelOp/@Table)[1]', 'nvarchar(128)')提取执行计划中实际扫描的表名——但这个只对物理表有效;对视图调用,更可靠的是直接搜 SQL 文本 - 推荐做法:JOIN
sys.dm_exec_sql_text(qs.sql_handle)获取原始语句,再用LIKE '%[schema].[view_name]%'匹配(注意方括号和 schema) - 避免漏匹配:
qt.text可能带换行或注释,用%view_name%比'view_name'更稳妥
为什么不能只看 sys.dm_exec_trigger_stats 或类似 DMV?
这些动态管理视图是为触发器、存储过程等可执行对象设计的,视图不是可执行单元,没有自己的 object_id 运行上下文。你查 sys.dm_exec_procedure_stats 或 sys.dm_exec_trigger_stats 都不会出现视图条目。
-
sys.views只存元数据,不记录调用历史 -
sys.dm_db_index_usage_stats对视图无效——视图没有索引(除非是索引视图) - 试图用
OBJECTPROPERTY(object_id, 'IsView')去筛sys.dm_exec_query_stats的object_id会失败,因为 ad-hoc 查询的object_id是 NULL
匹配时最容易错的三个地方
写 WHERE 条件时稍不注意,就会漏掉大量真实调用。
- 大小写敏感:如果数据库排序规则是区分大小写的(比如
SQL_Latin1_General_CP1_CS_AS),LIKE '%MyView%'就匹配不到myview,得用LOWER(qt.text) LIKE '%myview%' - schema 必须写全:
SELECT * FROM orders.v_customers不会命中LIKE '%v_customers%',必须写LIKE '%orders.v_customers%'或用正则逻辑(SQL Server 2017+ 可用STRING_SPLIT+CROSS APPLY拆分) - 动态 SQL 无法捕获:如果应用拼了
'SELECT * FROM ' + @view_name,那qt.text里根本没视图名,只会看到变量引用——这种只能靠扩展事件(XEvent)抓运行时参数值
真正难的不是查出调用语句,而是判断哪些调用是高频且低效的:同一个视图被不同应用以不同条件反复查,但只有带 WHERE date > '2025-01-01' 的那几条才走索引,其余都在扫全表。这时候光看 execution_count 没用,得结合 total_logical_reads 和执行计划里的 EstimatedRows 对齐看。

















