SQL Server中的执行计划缓存是数据库引擎用于存储已编译查询执行计划的内存区域,当客户端提交查询请求时,引擎会先检查缓存中是否存在匹配的执行计划,若存在则直接复用,避免重复编译带来的资源消耗。

执行计划缓存的基本概念
当SQL Server接收到一条SQL语句时,会经历解析、编译、优化三个步骤生成执行计划,这个执行计划会描述查询的具体执行方式,比如使用哪个索引、表的连接顺序、数据读取方式等。执行计划缓存就是把这些生成好的执行计划保存在内存中,供后续相同查询复用。
不是所有的执行计划都会被缓存,SQL Server有一套筛选规则,比如只编译一次的即席查询、参数化查询的执行计划会被缓存,而一些特殊语句比如创建表的DDL语句不会生成可缓存的执行计划。
执行计划的匹配规则
SQL Server判断两个查询是否可以使用同一个缓存执行计划时,会对比多个维度,主要包括:
- 查询的文本内容完全一致,包括空格、大小写、注释的差异都会导致无法匹配
- 查询使用的数据库上下文相同,比如两个查询分别在不同的数据库中执行,即使文本一致也不会复用缓存
- 查询的参数类型、长度等属性完全一致,参数不同可能导致执行计划不适用
执行计划缓存的核心作用
执行计划缓存的核心价值是降低查询的编译开销,提升整体查询性能,具体体现在以下几个方面:
减少CPU资源消耗
编译查询执行计划是一个CPU密集型操作,尤其是复杂的多表连接、嵌套子查询的编译过程会占用较多CPU资源。如果相同查询反复执行,每次都重新编译会浪费大量CPU,而复用缓存的执行计划可以完全省去这部分开销。
提升查询响应速度
编译过程需要消耗时间,对于高频执行的简单查询,编译时间可能占整个查询执行时间的很大比例。复用缓存执行计划后,查询可以直接进入执行阶段,响应速度会有明显提升。
降低内存碎片产生
如果每次查询都重新生成执行计划,会导致内存中频繁分配和释放小块内存,产生内存碎片。执行计划缓存会统一管理这些执行计划的存储,减少碎片产生的可能性。
执行计划缓存的存储结构
SQL Server的执行计划缓存整体是一个哈希表结构,通过查询的文本、上下文等信息计算哈希值,快速定位到对应的缓存项。缓存中的每一项都包含执行计划本身、相关的统计信息、缓存的时间等内容。
我们可以通过系统动态管理视图查询当前执行计划缓存的内容,比如使用以下语句查看缓存中所有的执行计划信息:
-- 查询执行计划缓存的基本信息
SELECT
cp.cacheobjtype, -- 缓存对象类型,比如Compiled Plan表示编译后的执行计划
cp.objtype, -- 对象类型,比如Adhoc表示即席查询,Prepared表示参数化查询
cp.refcounts, -- 引用次数,表示当前有多少会话正在使用该缓存项
cp.usecounts, -- 使用次数,表示该缓存项被复用的总次数
cp.size_in_bytes, -- 缓存项占用的内存大小
t.text -- 对应的查询文本
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) t
WHERE cp.cacheobjtype = 'Compiled Plan'
ORDER BY cp.usecounts DESC;
上面的查询会返回当前所有编译后的执行计划缓存项,按照使用次数从高到低排序,我们可以从中看到哪些查询的执行计划被频繁复用,哪些查询的执行计划几乎没有被使用过。
影响执行计划缓存复用的常见因素
在实际使用中,很多情况会导致执行计划无法被复用,缓存命中率降低,常见的影响因素包括:
- 查询文本不一致:比如同一个查询有的带了注释,有的没带,或者大小写不同,都会导致无法匹配缓存
- 非参数化查询:即席查询中如果直接拼接参数值,比如
SELECT * FROM user WHERE id = 1和SELECT * FROM user WHERE id = 2,会被认为是两个不同的查询,无法复用缓存 - 数据库选项不同:比如两个查询的数据库兼容级别不同,或者连接的数据库不同,都会导致缓存无法匹配
- 统计信息变化:当表的统计信息发生较大变化时,原有的执行计划可能不再最优,SQL Server会重新编译生成新的执行计划,旧的缓存项会被替换
注意:执行计划缓存占用的内存是SQL Server缓冲池的一部分,会受到SQL Server内存配置的限制,当内存不足时,SQL Server会根据淘汰策略移除不常用的缓存项。
SQL_Server执行计划缓存查询优化数据库性能修改时间:2026-07-11 21:54:30