带不同注释的同查询哈希参数化查询为何生成不同执行计划?
为什么查询哈希相同却生成了不同的执行计划?
这是个很容易让人困惑的问题,我来帮你拆解背后的核心原因:
1. 查询哈希与计划缓存存储键的本质区别
查询哈希是SQL Server用来识别逻辑等价查询的机制——它会忽略注释、空格、大小写这类不影响查询核心逻辑的文本差异,只聚焦查询的实际执行逻辑。但计划缓存的存储规则完全不同:
- 计划缓存的查找键包含原始查询文本的哈希值(而非查询哈希),再加上SET选项、数据库上下文、用户权限等一系列上下文信息。
- 你添加的注释属于原始查询文本的一部分,哪怕它对查询逻辑没有任何影响,也会改变原始文本的哈希值,导致计划缓存将其判定为两个不同的查询,进而生成并存储两个独立的执行计划。
2. 优化器判断逻辑与计划缓存复用规则的独立运作
Grant Fritchey在《SQL Server Execution Plans》里提到的“依据查询哈希判断是否需要优化”,指的是优化器层面的逻辑:
SQL Server优化器会依据查询哈希判断是否需要进行优化。
这句话的意思是,如果优化器发现当前查询的哈希和之前某个已完成优化的查询相同,它可以复用之前的部分优化结果(比如跳过重复的成本估算步骤),但这绝不代表它会直接复用已有的执行计划。优化器的优化逻辑和计划缓存的存储/复用规则是两个完全独立的环节:
- 优化器可能跳过部分优化流程,但最终还是会基于当前查询的完整缓存键(包括原始文本哈希)去匹配缓存,若没有找到完全匹配的条目,就会生成新的执行计划。
3. 其他可能的辅助影响因素
虽然你的场景主要由注释导致,但还有些常见情况也会让查询哈希相同却生成不同计划:
- SET选项差异:比如两次执行时
SET ANSI_NULLS、SET QUOTED_IDENTIFIER等选项不一致,哪怕查询逻辑完全相同,也会触发不同的执行计划。 - 统计信息变化:如果两次执行之间目标表的统计信息发生了更新,优化器可能基于新的数据分布生成更优的计划。
- 参数嗅探差异:若查询是参数化的,两次执行传入的参数值差异过大,优化器可能针对不同参数生成适配的计划(不过这不是你当前场景的主因)。
总结来说:查询哈希仅保证查询逻辑等价,但计划缓存的复用要求完全匹配包括原始文本哈希在内的所有缓存键,这就是你看到两个不同执行计划的核心原因。
内容的提问来源于stack exchange,提问作者bitsandbytes
相关产品推荐
相关产品推荐

