在SQL Server 2008中引入的围绕执行计划和缓冲的新功能被称为查询计划hash和查询hash。这是使用针对查询或查询计划的算法来生成二进制hash值的二进制对象。算法
能够从sys.dm_exec_query_stats或sys.dm_exec_requests检索查询计划hash和查询hash。虽然这是确认查询及其计划的一种机制,可是hash值不是惟一的。不类似的查询可能得出相同的hash,因此不能将其做为备份主键。sql
分别建立两个查询以下:服务器
SELECT * FROM PersonHunderThousand INNER JOIN Province ON PersonHunderThousand.PId = Province.Id WHERE PersonHunderThousand.Name = '郎徊刺' AND Province.Name = '广东' SELECT* from PersonHunderThousand INNER JOIN Province ON PersonHunderThousand.PId = Province.Id where PersonHunderThousand.Name = '习笑' AND Province.Name = '广东'
两个查询仅仅是from和where大小写不通以及第一个参数不一样,设计成INNER JOIN和两个条件稍微复杂点是为了防止简单参数化生成参数计划,再执行如下查询:工具
SELECT t.text,s.execution_count,s.query_hash,s.query_plan_hash FROM sys.dm_exec_query_stats s CROSS APPLY sys.dm_exec_sql_text(s.plan_handle) t
看到输出以下:性能
从上面的输入图能够看到,建立了两个不一样的计划,由于这些查询不是参数化的,它们太复杂以至不能考虑简单参数化,而且强制参数化关闭。这两个计划有相同的hash值,由于它们不一样的方面只是传递的值。大小写的差异对查询hash或查询计划hash来讲可有可无。spa
可是若是修改SELECT改成只返回一列:设计
SELECT PersonHunderThousand.ID FROM PersonHunderThousand INNER JOIN Province ON PersonHunderThousand.PId = Province.Id WHERE PersonHunderThousand.Name = '郎徊刺'
AND Province.Name ='广东'
该查询生成了一个新的计划。code
尽管查询的基本结构相同,返回列中的修改也足以改变查询hash和查询计划hash值。对象
由于数据分布和索引中的不一样可能致使相同的查询得出两个不一样的计划,query_hash可能相同,_query_plan_hash可能不一样blog
另外,有时就算只传入一个参数,可是由于根据统计,不一样的参数的执行计划不一样,也会建立两个计划:
SELECT * FROM PersonTenThousand WHERE Id = 1/100 --倘若传入的参数会生成不一样的执行计划,那么也会建立不一样的计划
查询计划hash和查询hash值对于跟踪彻底不一样的查询之间的常见问题多是有用的工具,可是正如所见,它们不能再每种可能性中获得一组精确的信息。它们增长了又一种确认查询性能可能低下的场所的有用工具。能够在将查询部署到生产环境仲以后捕捉查询的query_plan_hash,而后随时观察以了解其是否因数据变化而变化。由此,能够引用sys.dm_exec_query_stats根据计划跟踪集合的查询状态,可是要记住,这些集合的数据在服务器重启时会重置。