这绝对是一个错误。详细信息在旧的 Connect 站点上,并且不再可用,因为它已经退役,取而代之的是数量不确定的其他解决方案,包括第三方和第一方。
在测试对sp_BlitzCache的一些更改时(完全披露,我是作者之一),我遇到了我认为是我们代码中的错误。
有一次,我们匹配查询计划哈希以获得查询成本。我们这样做:statement.value('sum(/p:StmtSimple[xs:hexBinary(substring(@QueryHash, 3)) = xs:hexBinary(sql:column("b.QueryHash"))]/@ StatementSubTreeCost)', '浮动')
据我所知,这已经奏效了。然而,在一个奇怪的情况下,XML 中的子字符串抛出一个NULL
值,而计划显示成本为 0,尽管它相当高。
深入研究执行计划,我注意到一个问题哈希的查询计划哈希长 17 个字符,而其余的是 18 个字符。以下是示例:
QueryPlanHash="0x4410B0CA640CDA89" QueryPlanHash="0x2262FEA4CE645569" QueryPlanHash="0xED4F225CC0E97E5" -- 问题! QueryPlanHash="0xBF878EEE6DB955EA" QueryPlanHash="0x263B53BC8C14A452" QueryPlanHash="0x89F5F146CF4B476F" QueryPlanHash="0xEF47EA40805C8961" QueryPlanHash="0xB7BE27D6E43677A5" QueryPlanHash="0x815C54EC43A6A6E9"
查询计划哈希被列为——大概这应该总是相同binary 8
的长度,但是像我这样的人对二进制值了解多少?
稍微尝试一下 XQuery,我发现通过将子字符串更改为从第二个位置开始,它会得出一个有效(尽管不正确)的哈希值。
WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p)
SELECT
QueryPlanCost = statement.value('sum(/p:StmtSimple/@StatementSubTreeCost)', 'float'),
q.n.value('substring(@QueryPlanHash, 2)', 'binary(8)')
FROM #statements s
CROSS APPLY s.statement.nodes('/p:StmtSimple') AS q(n)
OPTION(RECOMPILE);
WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p)
SELECT
QueryPlanCost = statement.value('sum(/p:StmtSimple/@StatementSubTreeCost)', 'float'),
q.n.value('substring(@QueryPlanHash, 3)', 'binary(8)')
FROM #statements s
CROSS APPLY s.statement.nodes('/p:StmtSimple') AS q(n)
OPTION(RECOMPILE);
我正在运行 SQL Server 2016 SP1 (13.0.4001)。
有没有人遇到过这个?
17 个字符是值的有效长度binary 8
吗?
我认为发生这种情况是因为一个散列是奇数个字符。一个 valid
VARBINARY
需要有偶数个“对”才能正确表示数据。所以......你应该能够通过删除0x
,在开头放置一个“0”,抓住正确的 18 个字符,然后将其转换为来解决这个问题VARBINARY
。如果你想要更强大的东西,祝你好运,因为你需要除以 2 作为整数,并获得 2 的模,然后“做正确的事”来计算你的数据应该有多大。