来自sys.dm_exec_query_stats的Query_hash 定义 是:
query_hash:在查询上计算的二进制哈希值,用于识别具有相似逻辑的查询。您可以使用查询哈希来确定仅字面值不同的查询的聚合资源使用情况。
但是当我搜索一个特定的 query_hash(如下所示)时,我得到了多个在逻辑和size_in_bytes
(对于计划)上差异很大的查询文本。
注意:我使用的是 SQL Server 2016
DECLARE @QueryHashTest BINARY(8)
SET @QueryHashTest = CONVERT(BINARY(8), 'Ð…U¹üŒv¿')
SELECT
QCP.objtype
,qStat.query_hash,
CONVERT(VARCHAR(100), qStat.query_Hash) AS VARCHAR_query_hash
,sText.text AS QueryText
,QCP.size_in_bytes
,qStat.creation_time
,qp.query_plan
FROM (
SELECT query_hash,
COUNT(query_hash) AS PlanCount
FROM sys.dm_exec_query_stats
GROUP BY query_hash
) AS MultipleQ
INNER JOIN sys.dm_exec_query_stats qStat ON MultipleQ.query_hash = qStat.query_hash
INNER JOIN sys.dm_exec_cached_plans QCP
ON QCP.plan_handle = qStat.plan_handle
CROSS APPLY sys.dm_exec_sql_text(qStat.sql_handle) AS sText
CROSS APPLY sys.dm_exec_query_plan(qStat.plan_handle) AS qp
WHERE PlanCount > 1
AND QCP.objtype = 'Proc'
AND qStat.query_hash= @QueryHashTest
AND (size_in_bytes >= 2179072 OR size_in_bytes <= 262144)
ORDER BY size_in_bytes DESC
为什么不相关的查询显示相同的 query_hash?这是一个错误还是数据库中发生了意想不到的事情?
虽然散列冲突是可能的,但我怀疑正在发生的事情是你正在提取整个批次的文本,而不是特定的语句。具有多个语句的过程可以为每个语句获取一个缓存条目。如果某些语句在整个过程中是相同的,它们将具有相同的查询散列。让我演示一下:
使用以下查询查看每个 proc 中的相同语句如何分别显示。
如果您在问题中使用该查询,它无法提取相同的语句,因为它只查看批处理文本。
散列意味着将可能很大的东西“映射”到空间有限的东西(query_hash)。查询哈希是二进制 (8)。所以在 8 个字节中,您想要识别本质上可以具有无限可能的值的东西(查询)。底线是您可能会发生冲突——不同的查询导致相同的散列。这是意料之中的。