web-dev-qa-db-ja.com

SQL Server Management Studioでクエリ履歴を確認する方法

クエリ履歴はいくつかのログファイルに保存されていますか?もしそうなら、あなたはそれらの場所を見つける方法を教えてもらえますか?そうでない場合、あなたはそれを見る方法について何かアドバイスをください?

137
mstaniloiu

[ 以来、この質問 は重複して閉じられる可能性があります。]

SQL Serverが再起動されていない(そして計画が削除されていないなど)場合は、計画キャッシュでクエリを見つけることができる可能性があります。

SELECT t.[text]
FROM sys.dm_exec_cached_plans AS p
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
WHERE t.[text] LIKE N'%something unique about your query%';

Management Studioがクラッシュしたためにファイルを紛失した場合は、ここでリカバリファイルを見つけることができます。

C:\Users\<you>\Documents\SQL Server Management Studio\Backup Files\

それ以外の場合は、 Ed Harper's answer に記載されているSSMS Tools Packのように、クエリ履歴を保存するために他に何かを使用する必要があります。 SQL Server 2012以降では無料ではありません。あるいは、あなたのログイン名やホスト名でフィルタリングされた軽量のトレースを設定することもできます(ただし、プロファイラーではなくサーバーサイドのトレースを使用してください)。


@ Nenad-Zivkovicがコメントしたように、sys.dm_exec_query_statsに参加してlast_execution_timeで注文するのが役に立つかもしれません:

SELECT t.[text], s.last_execution_time
FROM sys.dm_exec_cached_plans AS p
INNER JOIN sys.dm_exec_query_stats AS s
   ON p.plan_handle = s.plan_handle
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
WHERE t.[text] LIKE N'%something unique about your query%'
ORDER BY s.last_execution_time DESC;
200
Aaron Bertrand

後の方だが詳細が追加されるので便利には…

既定でSSMSで実行されたクエリを確認する方法はありません。いくつかの選択肢があります。

トランザクションログの読み取り - これは独自の形式なので、これを行うのは簡単なことではありません。しかし、歴史的に実行された問い合わせ(SELECTを除く)を見る必要があるなら、これが唯一の方法です。

これには、 ApexSQL LogSQL Log Rescue (無料、ただしSQL 2000のみ)などのサードパーティ製ツールを使用できます。詳しくはこちらのスレッドをチェックしてください SQL Serverトランザクションログエクスプローラ/アナライザ

SQL Serverプロファイラ - 単に監査を開始したいだけで、以前に起こったことに興味がない場合に最適です。必要なトランザクションだけを選択するために必ずフィルタを使用してください。それ以外の場合は、大量のデータをすぐに入手することになります。

SQL Serverのトレース - すべてまたはほとんどのコマンドをキャプチャして後で解析できるトレースファイルに保存する場合に最適です。

トリガー - DMLをキャプチャし(selectを除く)、これらをデータベースのどこかに格納する場合に最適です。

49

SSMSツールパック は、とりわけ実行履歴を記録する機能を追加します。

16
Ed Harper

他の人が指摘したように、SQLプロファイラを使用できますが、sp_trace_ *システムストアドプロシージャを介してその機能を利用することもできます。たとえば、このSQLスニペットは(少なくとも2000年はSQL 2008でも同じだと思いますが、実行に10秒以上かかるすべてのクエリに対してRPC:CompletedイベントとSQL:BatchCompletedイベントをキャッチして保存します)。トレースファイルに出力して、後でSQLプロファイラで開くことができます。

DECLARE @TraceID INT
DECLARE @ON BIT
DECLARE @RetVal INT
SET @ON = 1

exec @RetVal = sp_trace_create @TraceID OUTPUT, 2, N'Y:\TraceFile.trc'
print 'This trace is Trace ID = ' + CAST(@TraceID AS NVARCHAR)
print 'Return value = ' + CAST(@RetVal AS NVARCHAR)
-- 10 = RPC:Completed
exec sp_trace_setevent @TraceID, 10, 1, @ON     -- Textdata
exec sp_trace_setevent @TraceID, 10, 3, @ON     -- DatabaseID
exec sp_trace_setevent @TraceID, 10, 12, @ON        -- SPID
exec sp_trace_setevent @TraceID, 10, 13, @ON        -- Duration
exec sp_trace_setevent @TraceID, 10, 14, @ON        -- StartTime
exec sp_trace_setevent @TraceID, 10, 15, @ON        -- EndTime

-- 12 = SQL:BatchCompleted
exec sp_trace_setevent @TraceID, 12, 1, @ON     -- Textdata
exec sp_trace_setevent @TraceID, 12, 3, @ON     -- DatabaseID
exec sp_trace_setevent @TraceID, 12, 12, @ON        -- SPID
exec sp_trace_setevent @TraceID, 12, 13, @ON        -- Duration
exec sp_trace_setevent @TraceID, 12, 14, @ON        -- StartTime
exec sp_trace_setevent @TraceID, 12, 15, @ON        -- EndTime

-- Filter for duration [column 13] greater than [operation 2] 10 seconds (= 10,000ms)
declare @duration bigint
set @duration = 10000
exec sp_trace_setfilter @TraceID, 13, 0, 2, @duration

Books Onlineから各トレースイベント、列などのIDを見つけることができます。 sp_trace_createsp_trace_setevent および sp_trace_setfiler sprocsを検索してください。その後、以下のようにトレースを制御することができます。

exec sp_trace_setstatus 15, 0       -- Stop the trace
exec sp_trace_setstatus 15, 1       -- Start the trace
exec sp_trace_setstatus 15, 2       -- Close the trace file and delete the trace settings

...ここで、 '15'はトレースIDです(sp_trace_createで報告されているように、上記の最初のスクリプトが開始します)。

どのトレースが実行されているかを確認することができます。

select * from ::fn_trace_getinfo(default)

私が注意を払うことになる唯一のこと - これがどれほどの負荷をかけるのか私にはわかりませんあなたのシステムで。いくらか追加されますが、「some」の大きさは、おそらくサーバーのビジー状態によって異なります。

6
Chris J

システムはそのようにクエリを記録しません。ただし、それを事前に実行したい場合は、SQL Profilerを使用して、受信した内容を記録し、Profilerの実行中にクエリを追跡することができます。

5
Thyamine

必要に応じて、 SQLプロファイラ でSQLクエリを監視できます。

3
Arsen Mkrtchyan

トレースプロファイラーが有効になっていないSQLサーバーでのアプリケーションアクティビティのトレースには、次のクエリを使用します。このメソッドは、DMVの代わりにQuery Store(SQL Server 2016以降)を使用します。これにより、履歴データを調べる能力が向上し、検索が速くなります。 sp_who/sp_whoisactiveではキャプチャできない短期間のクエリをキャプチャすることは非常に効率的です。

/* Adjust script to your needs.
    Run full script (F5) -> Interact with UI -> Run full script again (F5)
    Output will contain the queries completed in that timeframe.
*/

/* Requires Query Store to be enabled:
    ALTER DATABASE <db> SET QUERY_STORE = ON
    ALTER DATABASE <db> SET QUERY_STORE (OPERATION_MODE = READ_WRITE, MAX_STORAGE_SIZE_MB = 100000)
*/

USE <db> /* Select your DB */

IF OBJECT_ID('tempdb..#lastendtime') IS NULL
    SELECT GETUTCDATE() AS dt INTO #lastendtime
ELSE IF NOT EXISTS (SELECT * FROM #lastendtime)
    INSERT INTO #lastendtime VALUES (GETUTCDATE()) 

;WITH T AS (
SELECT 
    DB_NAME() AS DBName
    , s.name + '.' + o.name AS ObjectName
    , qt.query_sql_text
    , rs.runtime_stats_id
    , p.query_id
    , p.plan_id
    , CAST(p.last_execution_time AS DATETIME) AS last_execution_time
    , CASE WHEN p.last_execution_time > #lastendtime.dt THEN 'X' ELSE '' END AS New
    , CAST(rs.last_duration / 1.0e6 AS DECIMAL(9,3)) last_duration_s
    , rs.count_executions
    , rs.last_rowcount
    , rs.last_logical_io_reads
    , rs.last_physical_io_reads
    , q.query_parameterization_type_desc
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY plan_id, runtime_stats_id ORDER BY runtime_stats_id DESC) AS recent_stats_in_current_priod
    FROM sys.query_store_runtime_stats 
    ) AS rs
INNER JOIN sys.query_store_runtime_stats_interval AS rsi ON rsi.runtime_stats_interval_id = rs.runtime_stats_interval_id
INNER JOIN sys.query_store_plan AS p ON p.plan_id = rs.plan_id
INNER JOIN sys.query_store_query AS q ON q.query_id = p.query_id
INNER JOIN sys.query_store_query_text AS qt ON qt.query_text_id = q.query_text_id
LEFT OUTER JOIN sys.objects AS o ON o.object_id = q.object_id
LEFT OUTER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
CROSS APPLY #lastendtime
WHERE rsi.start_time <= GETUTCDATE() AND GETUTCDATE() < rsi.end_time
    AND recent_stats_in_current_priod = 1
    /* Adjust your filters: */
    -- AND (s.name IN ('<myschema>') OR s.name IS NULL)
UNION
SELECT NULL,NULL,NULL,NULL,NULL,NULL,dt,NULL,NULL,NULL,NULL,NULL,NULL, NULL
FROM #lastendtime
)
SELECT * FROM T
WHERE T.query_sql_text IS NULL OR T.query_sql_text NOT LIKE '%#lastendtime%' -- do not show myself
ORDER BY last_execution_time DESC

TRUNCATE TABLE #lastendtime
INSERT INTO #lastendtime VALUES (GETUTCDATE()) 
3
SELECT deqs.last_execution_time AS [Time], dest.text AS [Query], dest.*
FROM sys.dm_exec_query_stats AS deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest
WHERE dest.dbid = DB_ID('msdb')
ORDER BY deqs.last_execution_time DESC

これにより、クエリが実行された日時がわかります。

0
Jose Ortiz

ちょっとすぐに使える方法は、AutoHotKeyでソリューションを作成することです。私はこれを使っています、そしてそれは完璧ではありませんが、うまくいき無料です。基本的に、このスクリプトは以下にホットキーを割り当てます。 CTRL+SHIFT+R SSMSで選択したSQLをコピーします(CTRL+C)、日付スタンプのSQLファイルを保存してから、強調表示されたクエリを実行します(F5) AHKスクリプトに慣れていないのであれば、先頭のセミコロンがコメントです。

;CTRL+SHIFT+R to run a query that is first saved off
^+r::
;Copy
Send, ^c
; Set variables
EnvGet, HomeDir, USERPROFILE
FormatTime, DateString,,yyyyMMdd
FormatTime, TimeString,,hhmmss
; Make a spot to save the clipboard
FileCreateDir %HomeDir%\Documents\sqlhist\%DateString%
FileAppend, %Clipboard%, %HomeDir%\Documents\sqlhist\%DateString%\%TimeString%.sql
; execute the query
Send, {f5}
Return

最大の制限は、キーボードショートカットを使用せずに[実行]をクリックした場合、このスクリプトは機能しないことです。また、このスクリプトは選択したテキストだけをファイル全体から保存することはできません。しかし、スクリプトを変更してクエリを実行し、次にallを選択することもできます。CTRL+Aコピー/保存の前に.

「ファイル内の検索」機能を備えた最新のエディタを使用すると、SQL履歴を検索できます。あなたはあなたのクエリをクエリするためにSQLite3データベースにあなたのファイルを空想そしてスクレイピングすることさえできます。

0
mattmc3

management Studioを使用している場合は、「保存するたびにスクリプトを自動的に生成する」を使用できます。これは確かに記録されていません。あなたに役立つかどうか確認してください。

0
Hybridzz

関心のある照会が断続的に失敗する動的照会である場合は、動的ステートメントが作成された時点でSQLと日時およびユーザーを表に記録することができます。ただし、特定のプログラミングを実行する必要があり、余分な処理時間がかかるため、ケースバイケースで実行することになります。そのため、最も関心のある少数のクエリに対してのみ実行してください。しかし、実行された特定のステートメントのログを持つことは、月に一度失敗しただけの理由を見つけようとしているときに本当に役立ちます。動的なクエリは徹底的にテストするのが難しく、時にはうまくいかない特定の入力値を1つ取得することがあります。SQLが作成されたときにこのロギングを行うことは、構築されたSQLで具体的に何が行われたかを調べるための最善の方法です。

0
HLGEM