it-swarm.com.de

Anzeigen des Abfrageverlaufs in SQL Server Management Studio

Wird der Abfrageverlauf in einigen Protokolldateien gespeichert? Wenn ja, können Sie mir sagen, wie ich ihren Standort finde? Wenn nicht, können Sie mir einen Rat geben, wie ich es sehen soll?

140
mstaniloiu

[Da diese Frage wahrscheinlich als Duplikat geschlossen wird.]

Wenn SQL Server nicht neu gestartet wurde (und der Plan nicht entfernt wurde usw.), können Sie die Abfrage möglicherweise im Plan-Cache finden.

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%';

Wenn Sie die Datei aufgrund eines Absturzes von Management Studio verloren haben, können Sie hier möglicherweise Wiederherstellungsdateien finden:

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

Andernfalls müssen Sie in Zukunft etwas anderes verwenden, um Ihren Abfrageverlauf zu speichern, z. B. SSMS Tools Pack (siehe Ed Harpers Antwort ), obwohl dies in SQL Server 2012+ nicht kostenlos ist. Sie können auch eine einfache Ablaufverfolgung einrichten, die nach Ihrem Anmeldenamen oder Hostnamen gefiltert ist (verwenden Sie hierfür jedoch eine serverseitige Ablaufverfolgung, nicht den Profiler).


Wie @ Nenad-Zivkovic kommentierte, kann es hilfreich sein, sich sys.dm_exec_query_stats Anzuschließen und nach last_execution_time Zu bestellen:

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;
205
Aaron Bertrand

Später, aber hoffentlich nützlich, da es mehr Details hinzufügt ...

Es gibt keine Möglichkeit, Abfragen zu sehen, die standardmäßig in SSMS ausgeführt werden. Es gibt jedoch mehrere Möglichkeiten.

Transaktionsprotokoll lesen - das ist nicht einfach, da es im proprietären Format vorliegt. Wenn Sie jedoch Abfragen anzeigen möchten, die in der Vergangenheit ausgeführt wurden (außer SELECT), ist dies die einzige Möglichkeit.

Sie können hierfür Tools von Drittanbietern verwenden, z. B. ApexSQL Log und SQL Log Rescue (kostenlos, jedoch nur SQL 2000). Weitere Informationen finden Sie in diesem Thread hier SQL Server Transaction Log Explorer/Analyzer

SQL Server-Profiler - am besten geeignet, wenn Sie nur mit der Überwachung beginnen möchten und nicht daran interessiert sind, was früher passiert ist. Stellen Sie sicher, dass Sie Filter verwenden, um nur die Transaktionen auszuwählen, die Sie benötigen. Andernfalls erhalten Sie sehr schnell eine Menge Daten.

SQL Server-Ablaufverfolgung - am besten geeignet, wenn Sie alle oder die meisten Befehle erfassen und in einer Ablaufverfolgungsdatei speichern möchten, die später analysiert werden kann.

Trigger - am besten geeignet, wenn Sie DML erfassen (außer auswählen) und diese irgendwo in der Datenbank speichern möchten

49

SSMS-Toolpaket fügt unter anderem Funktionen zum Aufzeichnen des Ausführungsverlaufs hinzu.

16
Ed Harper

Wie andere angemerkt haben, können Sie SQL Profiler verwenden, aber Sie können seine Funktionalität auch über gespeicherte sp_trace_ * -Prozeduren des Systems nutzen. Zum Beispiel wird dieses SQL-Snippet (mindestens 2000; ich denke, es ist dasselbe für SQL 2008, aber Sie müssen es noch einmal überprüfen) catch RPC:Completed und SQL:BatchCompleted Ereignisse für alle Abfragen, deren Ausführung mehr als 10 Sekunden dauert, und Speichern der Ausgabe in einer Ablaufverfolgungsdatei, die Sie zu einem späteren Zeitpunkt in SQL Profiler öffnen können:

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

Die ID für jedes Trace-Ereignis, jede Spalte usw. finden Sie in der Onlinedokumentation. Suche einfach nach den Sprocs sp_trace_create , sp_trace_setevent und sp_trace_setfiler . Sie können den Trace dann wie folgt steuern:

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

... wobei '15' die Trace-ID ist (wie von sp_trace_create gemeldet, das das erste Skript oben auslöst).

Sie können überprüfen, mit welchen Traces gearbeitet wird:

select * from ::fn_trace_getinfo(default)

Das einzige, was ich zur Vorsicht sagen werde - Ich weiß nicht, wie viel Last dies auf Ihr System bringen wird ; es wird einige hinzufügen, aber wie groß das "einige" ist, hängt wahrscheinlich davon ab, wie beschäftigt Ihr Server ist.

6
Chris J

Das System zeichnet Anfragen nicht auf diese Weise auf. Wenn Sie jedoch wissen, dass Sie dies im Voraus tun möchten, können Sie mit SQL Profiler aufzeichnen, was eingeht, und Abfragen während der Ausführung von Profiler nachverfolgen.

5
Thyamine

Sie können SQL-Abfragen nach Bedarf mit SQL Profiler überwachen

3
Arsen Mkrtchyan

Ich verwende die folgende Abfrage zum Verfolgen der Anwendungsaktivität auf einem SQL-Server, auf dem der Trace-Profiler nicht aktiviert ist. Die Methode verwendet Query Store (SQL Server 2016+) anstelle der DMVs. Dies ermöglicht eine bessere Einsichtnahme in historische Daten sowie eine schnellere Suche. Es ist sehr effizient, kurzfristige Abfragen zu erfassen, die von sp_who/sp_whoisactive nicht erfasst werden können.

/* 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

Dies sollte Ihnen die Uhrzeit und das Datum der Ausführung einer Abfrage anzeigen

1
Jose Ortiz

Eine etwas out-of-the-box-Methode wäre, eine Lösung in AutoHotKey zu skripten. Ich benutze dies und es ist nicht perfekt, aber es funktioniert und ist kostenlos. Im Wesentlichen weist dieses Skript einen Hotkey zu CTRL+SHIFT+R Damit wird die ausgewählte SQL in SSMS kopiert (CTRL+C), speichern Sie eine SQL-Datei mit Datumsstempel und führen Sie dann die markierte Abfrage aus (F5). Wenn Sie nicht an AHK-Skripte gewöhnt sind, ist das führende Semikolon ein Kommentar.

;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

Die größten Einschränkungen bestehen darin, dass dieses Skript nicht funktioniert, wenn Sie auf "Ausführen" klicken, anstatt die Tastenkombination zu verwenden, und dass dieses Skript nicht die gesamte Datei - nur den ausgewählten Text - speichert. Sie können das Skript jedoch jederzeit ändern, um die Abfrage auszuführen, und dann alle auswählen (CTRL+A) vor dem Kopieren/Speichern.

Wenn Sie einen modernen Editor mit den Funktionen "In Dateien suchen" verwenden, können Sie Ihren SQL-Verlauf durchsuchen. Sie könnten sogar Lust bekommen und Ihre Dateien in eine SQLite3-Datenbank kratzen, um Ihre Abfragen abzufragen.

0
mattmc3

wenn Sie Management Studio verwenden, können Sie "Bei jedem Speichern automatisch ein Skript generieren" verwenden. Dies ist sicherlich keine Protokollierung. Überprüfe ob es für dich nützlich ist ..;)

0
Sin

Wenn es sich bei den Abfragen, an denen Sie interessiert sind, um dynamische Abfragen handelt, die zeitweise fehlschlagen, können Sie SQL sowie Datum, Uhrzeit und Benutzer zum Zeitpunkt der Erstellung der dynamischen Anweisung in einer Tabelle protokollieren. Dies erfolgt jedoch von Fall zu Fall, da hierfür eine spezielle Programmierung erforderlich ist und eine geringfügige zusätzliche Verarbeitungszeit erforderlich ist. Tun Sie dies nur für die wenigen Fragen, die Sie am meisten interessieren. Es kann jedoch hilfreich sein, ein Protokoll der spezifischen Anweisungen zu führen, wenn Sie herausfinden möchten, warum diese nur einmal im Monat fehlschlagen. Dynamische Abfragen sind nur schwer gründlich zu testen, und manchmal erhalten Sie einen bestimmten Eingabewert, der einfach nicht funktioniert. Wenn Sie diese Protokollierung zum Zeitpunkt der SQL-Erstellung durchführen, ist dies häufig die beste Möglichkeit, um festzustellen, was speziell in dem erstellten SQL-Code nicht vorhanden war.

0
HLGEM