SQL ServerクエリプランXML:QueryPlanHashの長さ


11

更新:これは間違いなくバグです。詳細については、こちらの接続アイテムをご覧ください。

sp_BlitzCacheへのいくつかの変更(完全な開示、私は作成者の1人)をテストしているときに、コードのバグだと思ったものに遭遇しました。

ある時点で、クエリコストを取得するためにクエリプランハッシュを照合しています。私たちはそのようにしています:

statement.value('sum(/p:StmtSimple[xs:hexBinary(substring(@QueryHash, 3)) =
    xs:hexBinary(sql:column("b.QueryHash"))]/@StatementSubTreeCost)', 'float')

これは、私が見た限りではうまくいきました。ただし、奇妙なケースの1つとして、XMLの部分文字列がNULL値をスローし、プランのコストはかなり高いにもかかわらず、コストが0でした。

掘り下げる実行計画(フル開示は、ホストが計画を貼り付けていること、会社のための私の仕事は)、私は、クエリプランハッシュは一つの問題ハッシュのための残りが18ここである例でありながら、17文字の長さだったことに気づきました。

QueryPlanHash = "0x4410B0CA640CDA89"
QueryPlanHash = "0x2262FEA4CE645569" 
QueryPlanHash = "0xED4F225CC0E97E5"-問題!
QueryPlanHash = "0xBF878EEE6DB955EA"
QueryPlanHash = "0x263B53BC8C14A452"
QueryPlanHash = "0x89F5F146CF4B476F"
QueryPlanHash = "0xEF47EA40805C8961"
QueryPlanHash = "0xB7BE27D6E43677A5"
QueryPlanHash = "0x815C54EC43A6A6E9"

クエリプランハッシュはaとしてリストされていますBINARY 8-おそらくこれは常に同じ長さでなければなりませんが、私のような人はバイナリ値について何を知っていますか?

XQueryを少し試してみたところ、2番目の位置から開始するように部分文字列を変更すると、有効な(正しくないとしても)ハッシュ値が得られることがわかりました。

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値の有効な長さですか?

これは、Connectアイテムを取得する必要があるバグのように見えますか?

回答:


11

これは、1つのハッシュが奇数の文字であるために起こっていると思います。有効なVARBINARYデータを正しく表現するには、偶数の「ペア」が必要です。したがって、これを解決するには0x、を削除し、先頭に「0」を付け、右の18文字を取得してからにキャストしVARBINARYます。

CONVERT(VARBINARY(MAX), RIGHT('0' + SUBSTRING('0xED4F225CC0E97E5', 3, 20), 18), 2)

より堅牢で幸運なものが必要な場合は、整数として2で除算し、2のモジュロを取得してから、「正しいことを行う」ことでデータの大きさを把握する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.