将 sys.dm_exec_sql_text 中的相似查询组合在一起

pac*_*ely 3 sql-server-2008 sql-server dmv plan-cache

我正在分析支持 3rd 方应用程序的 2008 实例。

该应用程序将生成 SQL 代码,然后将其作为临时查询发送到数据库。

我正在使用此查询(基于 Glenn Berry 脚本):

SELECT
    qs.creation_time
    ,qs.last_execution_time
    ,qs.execution_count
    ,qs.total_worker_time
    ,qs.total_physical_reads
    ,qs.total_logical_writes
    ,qs.total_logical_reads
    ,qs.plan_handle
    ,qt.text
    ,qt.dbid
FROM 
        sys.dm_exec_query_stats AS qs WITH (NOLOCK)
        CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE
    qt.dbid >= 7
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)

我的问题是我正在为非常相似的查询获得数千个计划,即

SELECT * FROM customers WHERE name = 'bob'
SELECT * FROM customers WHERE name = 'bill'
Run Code Online (Sandbox Code Playgroud)

(实际上查询非常大,最多 3000 个字符)

这使得将数据转换为适合高级分析的格式几乎是不可能的。

是否可以快速比较 2 个 SQL 查询并查看它们是否几乎相同?然后我会随机选择其中一个查询,并将所有活动与该查询进行分组。(我试过 DIFFERENCE 但速度很慢)

SQL 是否已经存储了一个类似于 MD5 Hash sql_handle 的值,它允许它查看两个查询是否相似并因此重用相同的计划?(如果存在这样的值,那么我会对此进行分组)

我对存储过程没有这个问题,因为正在重用相同的计划。我只想将所有类似的临时人员组合在一起。

For*_*est 9

您要查找的是SQL Server 2008 中query_hash引入的列。您可以在. 以下是查看前 20 种最常见模式的示例查询:sys.dm_exec_query_stats

WITH agg AS (
SELECT TOP 20 COUNT(*) AS similar_query_count, query_hash
FROM sys.dm_exec_query_stats qs
GROUP BY qs.query_hash
ORDER BY similar_query_count DESC
)

SELECT similar_query_count,
SUBSTRING(st.text, (ca.statement_start_offset/2) + 1,  
    ((CASE ca.statement_end_offset   
        WHEN -1 THEN DATALENGTH(st.text)  
        ELSE ca.statement_end_offset 
    END - ca.statement_start_offset)/2) + 1
) AS statement_text
,st.text AS full_text
FROM agg
CROSS APPLY (SELECT TOP 1 sql_handle, statement_start_offset, statement_end_offset FROM sys.dm_exec_query_stats WHERE query_hash = agg.query_hash) ca
CROSS APPLY sys.dm_exec_sql_text(ca.sql_handle) st
Run Code Online (Sandbox Code Playgroud)

另一个相关的列是query_plan_hash,它对于查看类似的执行计划很有用。