План запитів SQL Server XML: довжина QueryPlanHash


11

ОНОВЛЕННЯ: Це, безумовно, помилка. Для отримання детальної інформації див цей елемент підключення .

Під час тестування деяких змін sp_BlitzCache (повне розкриття інформації, я один з авторів), я натрапив на те, що, на мою думку, помилку в нашому коді.

В один момент ми підбираємо хеш-план плану запитів, щоб отримати вартість запиту. Ми робимо це приблизно так:

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

Наскільки я бачив, це спрацювало. Однак, в одному дивному випадку, підрядок у XML кидав NULLзначення, і план показував вартість 0, незважаючи на те, що він був досить високим.

Заглибившись у план виконання (повне розкриття інформації, я працюю в компанії, яка розміщує програму Paste The Plan), я помітив, що хеш планування для одного хешу проблем був 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значення?

Чи схоже це на помилку, яка має отримати елемент Connect?

Відповіді:


11

Я думаю, що це відбувається тому, що один хеш - це непарна кількість символів. Для VARBINARYкоректного представлення даних дійсно потрібно мати парне число "пар". Отже ... ви повинні мати змогу вирішити це, видаливши на початку 0x, поставивши "0", захопивши правильні 18 символів, а потім закинувши його VARBINARY.

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

Якщо ви хочете чогось більш надійного, удачі, тому що вам потрібно розділити на 2 як ціле число, і отримати модуль 2, а потім "зробити правильно", щоб зрозуміти, наскільки великими повинні бути ваші дані.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.