Kế hoạch truy vấn SQL Server XML: QueryPlanHash Chiều dài


11

CẬP NHẬT: Đây chắc chắn là một lỗi. Để biết chi tiết đầy đủ, xem Mục Kết nối này .

Trong khi thử nghiệm một số thay đổi đối với sp_BlitzCache (công bố đầy đủ, tôi là một trong những tác giả), tôi đã xem qua những gì tôi nghĩ là một lỗi trong mã của chúng tôi.

Tại một thời điểm, chúng tôi phù hợp với Hash kế hoạch truy vấn để có được chi phí truy vấn. Chúng tôi làm điều đó về như vậy:

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

Điều này, theo như tôi đã thấy, đã làm việc. Tuy nhiên, trong một trường hợp kỳ lạ, chuỗi con trong XML đã ném một NULLgiá trị và kế hoạch đã hiển thị chi phí bằng 0, mặc dù nó khá cao.

Đào sâu vào kế hoạch thực hiện (công bố đầy đủ, tôi làm việc cho công ty tổ chức Paste The Plan), tôi nhận thấy rằng Hash kế hoạch truy vấn cho một hàm băm có độ dài 17 ký tự, trong khi phần còn lại là 18. Dưới đây là các ví dụ:

Truy vấnPlanHash = "0x4410B0CA640CDA89"
Truy vấnPlanHash = "0x2262FEA4CE645569" 
QueryPlanHash = "0xED4F225CC0E97E5" - Vấn đề!
Truy vấnPlanHash = "0xBF878EEE6DB955EA"
Truy vấnPlanHash = "0x263B53BC8C14A452"
Truy vấnPlanHash = "0x89F5F146CF4B476F"
Truy vấnPlanHash = "0xEF47EA40805C8961"
Truy vấnPlanHash = "0xB7BE27D6E43677A5"
Truy vấnPlanHash = "0x815C54EC43A6A6E9"

Truy vấn kế hoạch Hash được liệt kê dưới dạng BINARY 8- có lẽ điều này sẽ luôn luôn có cùng độ dài, nhưng một người như tôi biết gì về các giá trị nhị phân?

Chơi với XQuery một chút, tôi thấy rằng bằng cách thay đổi chuỗi con để bắt đầu ở vị trí thứ hai, nó sẽ đưa ra một giá trị băm hợp lệ (mặc dù không chính xác).

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

Quả hạch

Tôi đang chạy SQL Server 2016, SP1 (13.0.4001).

Có ai đã chạy vào đây trước?

Là 17 ký tự có độ dài hợp lệ cho một BINARY 8giá trị?

Điều này có giống như một lỗi sẽ nhận được một mục Kết nối không?

Câu trả lời:


11

Tôi nghĩ điều này đang xảy ra bởi vì một hàm băm là một số lượng ký tự lẻ. Một hợp lệ VARBINARYsẽ cần phải có một số "cặp" chẵn để thể hiện chính xác dữ liệu. Vì vậy, ... bạn sẽ có thể giải quyết vấn đề này bằng cách loại bỏ 0x, đặt '0' ở đầu, lấy đúng 18 ký tự và sau đó chuyển nó sang VARBINARY.

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

Nếu bạn muốn thứ gì đó mạnh mẽ hơn, chúc may mắn, bởi vì bạn cần chia 2 cho một số nguyên và lấy modulo bằng 2, sau đó "làm điều đúng đắn" để tìm ra dữ liệu của bạn sẽ lớn như thế nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.