XML del piano di query di SQL Server: Lunghezza QueryPlanHash


11

AGGIORNAMENTO: Questo è sicuramente un bug. Per i dettagli completi, vedere questo articolo Connect .

Durante il test di alcune modifiche a sp_BlitzCache (divulgazione completa, sono uno degli autori), mi sono imbattuto in quello che pensavo fosse un bug nel nostro codice.

A un certo punto, stiamo abbinando l'hash del piano di query per ottenere il costo della query. Lo facciamo in questo modo:

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

Questo, per quanto ho visto, ha funzionato. Tuttavia, in uno strano caso, la sottostringa nell'XML stava generando un NULLvalore e il piano mostrava un costo pari a 0, nonostante fosse piuttosto elevato.

Scavando nel piano di esecuzione (divulgazione completa, lavoro per la società che ospita Paste The Plan), ho notato che l'hash del piano di query per l'hash di un problema era lungo 17 caratteri, mentre gli altri sono 18. Ecco alcuni esempi:

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

Quash Plan Hash è elencato come BINARY 8- presumibilmente dovrebbe sempre avere la stessa lunghezza, ma cosa sa un tipo come me dei valori binari?

Giocando un po 'con XQuery, ho scoperto che cambiando la sottostringa per iniziare dalla seconda posizione, sarebbe emerso un valore di hash valido (anche se errato).

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);

Noccioline

Sto eseguendo SQL Server 2016, SP1 (13.0.4001).

È già successo a qualcuno?

17 caratteri hanno una lunghezza valida per un BINARY 8valore?

Sembra un bug che dovrebbe ottenere un elemento Connect?

Risposte:


11

Penso che questo accada perché quell'hash è un numero dispari di personaggi. Un valido VARBINARYdovrà disporre di un numero pari di "coppie" per rappresentare correttamente i dati. Quindi ... dovresti essere in grado di risolverlo rimuovendo 0x, mettendo uno "0" all'inizio, afferrando i 18 caratteri giusti e poi lanciandolo su VARBINARY.

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

Se vuoi qualcosa di più robusto, buona fortuna, perché dovresti dividere per 2 come numero intero e ottenere il modulo di 2, quindi "fare la cosa giusta" per capire quanto dovrebbero essere grandi i tuoi dati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.