web-dev-qa-db-fra.com

Comment voir l'historique des requêtes dans SQL Server Management Studio

L'historique des requêtes est-il stocké dans certains fichiers journaux? Si oui, pouvez-vous me dire comment trouver leur emplacement? Si non, pouvez-vous me donner un conseil sur la façon de le voir?

140
mstaniloiu

[Puisque cette question sera probablement fermé en double.]

Si SQL Server n'a pas été redémarré (et que le plan n'a pas été expulsé, etc.), vous pourrez peut-être trouver la requête dans le cache du plan.

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

Si vous avez perdu le fichier parce que Management Studio s'est écrasé, vous pourrez peut-être trouver les fichiers de récupération ici:

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

Sinon, vous devrez utiliser un autre outil pour vous aider à enregistrer l'historique de vos requêtes, tel que SSMS Tools Pack, comme mentionné dans réponse d'Ed Harper - bien que ce ne soit pas gratuit dans SQL Server 2012+. Vous pouvez également configurer un traçage léger filtré sur votre nom d'utilisateur ou votre nom d'hôte (mais utilisez pour cela un traçage côté serveur, et non pas Profiler).


Comme @ Nenad-Zivkovic a commenté, il pourrait être utile de rejoindre le sys.dm_exec_query_stats et de le commander par 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;
205
Aaron Bertrand

Plus tard que prévu mais utile car il ajoute plus de détails…

Il n'y a aucun moyen de voir les requêtes exécutées dans SSMS par défaut. Il y a plusieurs options cependant.

Lire le journal des transactions - ce n’est pas une chose facile à faire car son format est propriétaire. Toutefois, si vous avez besoin de voir des requêtes qui ont été exécutées historiquement (sauf SELECT), c'est le seul moyen.

Vous pouvez utiliser des outils tiers, tels que ApexSQL Log et SQL Log Rescue (gratuit, mais SQL 2000 uniquement). Consultez ce fil pour plus de détails ici Explorateur/analyseur de journaux de transactions SQL Server

Profileur SQL Server - idéal si vous voulez juste commencer à auditer et que vous n'êtes pas intéressé par ce qui s'est passé plus tôt. Assurez-vous d’utiliser des filtres pour sélectionner uniquement les transactions dont vous avez besoin. Sinon, vous allez vous retrouver avec une tonne de données très rapidement.

Trace SQL Server - idéale si vous souhaitez capturer toutes les commandes ou la plupart des commandes et les conserver dans un fichier de trace pouvant être analysé ultérieurement.

Déclencheurs - mieux adaptés si vous souhaitez capturer DML (sauf select) et les stocker quelque part dans la base de données

49
Djordje Kujundzic

pack d'outils SSMS ajoute une fonctionnalité à l'historique d'exécution des enregistrements, entre autres.

16
Ed Harper

Comme d'autres l'ont noté, vous pouvez utiliser SQL Profiler, mais vous pouvez également exploiter ses fonctionnalités via les procédures système stockées sp_trace_ *. Par exemple, cet extrait de code SQL va (du moins en 2000; je pense que c'est la même chose pour SQL 2008 mais que vous devrez revérifier) ​​attraper les événements RPC:Completed et SQL:BatchCompleted pour toutes les requêtes qui prennent le relais. 10 secondes pour s'exécuter et enregistrer la sortie dans un fichier de trace que vous pourrez ouvrir ultérieurement dans le profileur 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

Vous pouvez trouver l'ID de chaque événement de suivi, colonne, etc. à partir de la documentation en ligne; il suffit de rechercher sp_trace_create , sp_trace_setevent et sp_trace_setfiler sprocs. Vous pouvez ensuite contrôler la trace comme suit:

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

... où '15' est l'ID de trace (comme indiqué par sp_trace_create, que le premier script supprime ci-dessus).

Vous pouvez vérifier quelles traces fonctionnent avec:

select * from ::fn_trace_getinfo(default)

La seule chose que je vais dire avec prudence - Je ne sais pas combien de charge cela va mettre sur votre système; cela en ajoutera quelques-uns, mais la taille de "certains" dépend probablement de l'occupation de votre serveur.

6
Chris J

Le système n'enregistre pas les requêtes de cette façon. Si vous savez que vous souhaitez le faire à l'avance, vous pouvez utiliser SQL Profiler pour enregistrer ce qui arrive et suivre les requêtes pendant son exécution.

5
Thyamine

Vous pouvez surveiller les requêtes SQL par Générateur de profils SQL si vous en avez besoin

3
Arsen Mkrtchyan

J'utilise la requête ci-dessous pour suivre l'activité des applications de suivi sur un serveur SQL sur lequel le profileur de trace n'est pas activé. La méthode utilise Query Store (SQL Server 2016+) à la place du fichier DMV. Cela donne une meilleure capacité à consulter des données historiques, ainsi que des recherches plus rapides. Il est très efficace de capturer les requêtes de courte durée qui ne peuvent pas être capturées par 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
Martin Thøgersen
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

Cela devrait vous montrer l'heure et la date à laquelle une requête a été exécutée

1
Jose Ortiz

Une méthode légèrement prête à l'emploi consisterait à écrire une solution dans AutoHotKey. Je l'utilise, et ce n'est pas parfait, mais fonctionne et est gratuit. Essentiellement, ce script assigne un raccourci clavier à CTRL+SHIFT+R qui copie le code SQL sélectionné dans SSMS (CTRL+C), enregistrez un fichier SQL d'horodatage, puis exécutez la requête en surbrillance (F5). Si vous n'êtes pas habitué aux scripts AHK, le point-virgule est un commentaire.

;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

Les principales limitations sont que ce script ne fonctionnera pas si vous cliquez sur "Exécuter" plutôt que d'utiliser le raccourci clavier, et ce script ne sauvegardera pas le fichier entier, mais uniquement le texte sélectionné. Mais vous pouvez toujours modifier le script pour exécuter la requête, puis sélectionner tout (CTRL+A) avant la copie/sauvegarde.

L'utilisation d'un éditeur moderne doté des fonctionnalités de "recherche dans les fichiers" vous permettra de rechercher votre historique SQL. Vous pourriez même avoir envie de copier vos fichiers dans une base de données SQLite3 pour interroger vos requêtes.

0
mattmc3

vous pouvez utiliser "Générer automatiquement un script à chaque sauvegarde" si vous utilisez Management Studio. Ce n'est pas certainement en train de vous connecter. Vérifiez si utile pour vous ..;)

0
Sin

Si les requêtes qui vous intéressent sont des requêtes dynamiques qui échouent par intermittence, vous pouvez consigner le code SQL, l'heure et l'heure utilisateur dans une table au moment de la création de l'instruction dynamique. Cela se ferait au cas par cas, car cela nécessite une programmation spécifique et prend un peu plus de temps de traitement. Ne le faites que pour les quelques requêtes qui vous préoccupent le plus. Avoir un journal des instructions spécifiques exécutées peut vraiment aider lorsque vous essayez de comprendre pourquoi cela échoue une fois par mois. Les requêtes dynamiques sont difficiles à tester de manière approfondie. Parfois, vous obtenez une valeur d'entrée spécifique qui ne fonctionne tout simplement pas. Cette journalisation au moment de la création du code SQL est souvent le meilleur moyen de voir ce qui n'a pas été spécifiquement créé dans le SQL.

0
HLGEM