web-dev-qa-db-ja.com

sys.dm_exec_sql_textで同様のクエリをグループ化します

サードパーティのアプリをサポートする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)

私の問題は、非常によく似たクエリに対して何千もの計画を立てていることです。

SELECT * FROM customers WHERE name = 'bob'
SELECT * FROM customers WHERE name = 'bill'

(実際にはクエリは非常に大きく、最大3000文字です)

高レベルの分析に理想的な形式にデータを取得することはほとんど不可能になっています。

2つのSQLクエリをすばやく比較して、それらがほぼ同じクエリであるかどうかを確認することは可能ですか?次に、クエリの1つをランダムに選択し、その1つのクエリに対してすべてのアクティビティをグループ化します。 (私はDIFFERENCEを試しましたが、非常に遅いです)

SQLは、2つのクエリが類似しているかどうかを確認して同じプランを再利用できるようにするMD5ハッシュsql_handleに類似した値をすでに格納していますか? (そのような値が存在する場合、私はそれをグループ化します)

同じプランが再利用されているため、ストアドプロシージャでこの問題は発生しません。私が一緒にグループ化したいのは、すべての類似したアドホックです。

3
pacreely

探しているのは、 SQL Server 2008 で導入された列query_hashです。これはsys.dm_exec_query_statsにあります。最も一般的な上位20のパターンを確認するためのサンプルクエリを次に示します。

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

もう1つの関連する列はquery_plan_hashで、これは同様の実行プランを確認するのに役立ちます。

9
Forrest