O histórico de consultas é armazenado em alguns arquivos de log? Se sim, você pode me dizer como encontrar a localização deles? Caso contrário, você pode me dar algum conselho sobre como vê-lo?
O histórico de consultas é armazenado em alguns arquivos de log? Se sim, você pode me dizer como encontrar a localização deles? Caso contrário, você pode me dar algum conselho sobre como vê-lo?
Respostas:
[Como essa pergunta provavelmente será encerrada como duplicada.]
Se o SQL Server não tiver sido reiniciado (e o plano não tiver sido despejado etc.), você poderá encontrar a consulta no cache do plano.
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%';
Se você perdeu o arquivo porque o Management Studio travou, poderá encontrar arquivos de recuperação aqui:
C:\Users\<you>\Documents\SQL Server Management Studio\Backup Files\
Caso contrário, você precisará usar outra coisa a seguir para ajudá-lo a salvar seu histórico de consultas, como o SSMS Tools Pack, conforme mencionado na resposta de Ed Harper - embora não seja gratuito no SQL Server 2012+. Ou você pode configurar algum rastreamento leve filtrado no seu nome de login ou host (mas use um rastreamento do lado do servidor, não o Profiler, para isso).
Como comentou @ Nenad-Zivkovic, pode ser útil ingressar sys.dm_exec_query_stats
e solicitar 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;
sys.dm_exec_query_stats
e pesquisar ou ordem porlast_execution_time
Tarde, mas espero que útil, pois acrescenta mais detalhes ...
Não há como ver as consultas executadas no SSMS por padrão. Existem várias opções embora.
Lendo o log de transações - isso não é algo fácil de fazer porque está em formato proprietário. No entanto, se você precisar ver consultas que foram executadas historicamente (exceto SELECT), essa é a única maneira.
Você pode usar ferramentas de terceiros para isso, como ApexSQL Log e SQL Log Rescue (gratuito, mas apenas para o SQL 2000). Confira este tópico para obter mais detalhes aqui Explorador / Analisador de Log de Transações do SQL Server
Perfilador do SQL Server - mais adequado se você deseja iniciar a auditoria e não está interessado no que aconteceu anteriormente. Use filtros para selecionar apenas as transações necessárias. Caso contrário, você acabará com toneladas de dados muito rapidamente.
Rastreamento do SQL Server - mais adequado se você deseja capturar todos ou a maioria dos comandos e mantê-los no arquivo de rastreamento que pode ser analisado posteriormente.
Acionadores - mais adequado se você deseja capturar DML (exceto selecionar) e armazená-los em algum lugar no banco de dados
O pacote de ferramentas SSMS adiciona funcionalidade ao registro do histórico de execução, entre outras coisas.
Como outros observaram, você pode usar o SQL Profiler, mas também pode aproveitar sua funcionalidade por meio de procedimentos armazenados do sistema sp_trace_ *. Por exemplo, esse snippet SQL (pelo menos em 2000; acho que é o mesmo para o SQL 2008, mas você terá que verificar duas vezes) capturas RPC:Completed
e SQL:BatchCompleted
eventos para todas as consultas que demoram mais de 10 segundos para executar e salvar a saída em um arquivo de rastreamento que você pode abrir no SQL Profiler posteriormente:
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
Você pode encontrar o ID de cada evento de rastreamento, colunas etc. nos Manuais Online; basta procurar os sprocs sp_trace_create , sp_trace_setevent e sp_trace_setfiler . Você pode controlar o rastreamento da seguinte maneira:
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
... onde '15' é o ID de rastreamento (conforme relatado por sp_trace_create, que o primeiro script inicia acima).
Você pode verificar para ver com que rastreamentos estão sendo executados:
select * from ::fn_trace_getinfo(default)
A única coisa que direi com cautela - não sei quanta carga isso colocará no seu sistema; ele adicionará alguns, mas o tamanho desses "alguns" provavelmente depende da ocupação do servidor.
Eu uso a consulta abaixo para rastrear a atividade do aplicativo em um servidor SQL que não possui o gerenciador de perfis de rastreamento ativado. O método usa o Query Store (SQL Server 2016 ou superior) em vez das DMVs. Isso oferece uma melhor capacidade de analisar dados históricos, bem como pesquisas mais rápidas. É muito eficiente capturar consultas de execução curta que não podem ser capturadas por 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())
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
Isso deve mostrar a hora e a data em que uma consulta foi executada
Você pode monitorar consultas SQL pelo SQL Profiler, se precisar
O histórico de consultas pode ser visualizado usando as visualizações do sistema:
Por exemplo, usando a seguinte consulta:
select top(100)
creation_time,
last_execution_time,
execution_count,
total_worker_time/1000 as CPU,
convert(money, (total_worker_time))/(execution_count*1000)as [AvgCPUTime],
qs.total_elapsed_time/1000 as TotDuration,
convert(money, (qs.total_elapsed_time))/(execution_count*1000)as [AvgDur],
total_logical_reads as [Reads],
total_logical_writes as [Writes],
total_logical_reads+total_logical_writes as [AggIO],
convert(money, (total_logical_reads+total_logical_writes)/(execution_count + 0.0)) as [AvgIO],
[sql_handle],
plan_handle,
statement_start_offset,
statement_end_offset,
plan_generation_num,
total_physical_reads,
convert(money, total_physical_reads/(execution_count + 0.0)) as [AvgIOPhysicalReads],
convert(money, total_logical_reads/(execution_count + 0.0)) as [AvgIOLogicalReads],
convert(money, total_logical_writes/(execution_count + 0.0)) as [AvgIOLogicalWrites],
query_hash,
query_plan_hash,
total_rows,
convert(money, total_rows/(execution_count + 0.0)) as [AvgRows],
total_dop,
convert(money, total_dop/(execution_count + 0.0)) as [AvgDop],
total_grant_kb,
convert(money, total_grant_kb/(execution_count + 0.0)) as [AvgGrantKb],
total_used_grant_kb,
convert(money, total_used_grant_kb/(execution_count + 0.0)) as [AvgUsedGrantKb],
total_ideal_grant_kb,
convert(money, total_ideal_grant_kb/(execution_count + 0.0)) as [AvgIdealGrantKb],
total_reserved_threads,
convert(money, total_reserved_threads/(execution_count + 0.0)) as [AvgReservedThreads],
total_used_threads,
convert(money, total_used_threads/(execution_count + 0.0)) as [AvgUsedThreads],
case
when sql_handle IS NULL then ' '
else(substring(st.text,(qs.statement_start_offset+2)/2,(
case
when qs.statement_end_offset =-1 then len(convert(nvarchar(MAX),st.text))*2
else qs.statement_end_offset
end - qs.statement_start_offset)/2 ))
end as query_text,
db_name(st.dbid) as database_name,
object_schema_name(st.objectid, st.dbid)+'.'+object_name(st.objectid, st.dbid) as [object_name],
sp.[query_plan]
from sys.dm_exec_query_stats as qs with(readuncommitted)
cross apply sys.dm_exec_sql_text(qs.[sql_handle]) as st
cross apply sys.dm_exec_query_plan(qs.[plan_handle]) as sp
WHERE st.[text] LIKE '%query%'
As consultas em execução atuais podem ser vistas usando o seguinte script:
select ES.[session_id]
,ER.[blocking_session_id]
,ER.[request_id]
,ER.[start_time]
,DateDiff(second, ER.[start_time], GetDate()) as [date_diffSec]
, COALESCE(
CAST(NULLIF(ER.[total_elapsed_time] / 1000, 0) as BIGINT)
,CASE WHEN (ES.[status] <> 'running' and isnull(ER.[status], '') <> 'running')
THEN DATEDIFF(ss,0,getdate() - nullif(ES.[last_request_end_time], '1900-01-01T00:00:00.000'))
END
) as [total_time, sec]
, CAST(NULLIF((CAST(ER.[total_elapsed_time] as BIGINT) - CAST(ER.[wait_time] AS BIGINT)) / 1000, 0 ) as bigint) as [work_time, sec]
, CASE WHEN (ER.[status] <> 'running' AND ISNULL(ER.[status],'') <> 'running')
THEN DATEDIFF(ss,0,getdate() - nullif(ES.[last_request_end_time], '1900-01-01T00:00:00.000'))
END as [sleep_time, sec] --Время сна в сек
, NULLIF( CAST((ER.[logical_reads] + ER.[writes]) * 8 / 1024 as numeric(38,2)), 0) as [IO, MB]
, CASE ER.transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncommited'
WHEN 2 THEN 'ReadCommited'
WHEN 3 THEN 'Repetable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot'
END as [transaction_isolation_level_desc]
,ER.[status]
,ES.[status] as [status_session]
,ER.[command]
,ER.[percent_complete]
,DB_Name(coalesce(ER.[database_id], ES.[database_id])) as [DBName]
, SUBSTRING(
(select top(1) [text] from sys.dm_exec_sql_text(ER.[sql_handle]))
, ER.[statement_start_offset]/2+1
, (
CASE WHEN ((ER.[statement_start_offset]<0) OR (ER.[statement_end_offset]<0))
THEN DATALENGTH ((select top(1) [text] from sys.dm_exec_sql_text(ER.[sql_handle])))
ELSE ER.[statement_end_offset]
END
- ER.[statement_start_offset]
)/2 +1
) as [CURRENT_REQUEST]
,(select top(1) [text] from sys.dm_exec_sql_text(ER.[sql_handle])) as [TSQL]
,(select top(1) [objectid] from sys.dm_exec_sql_text(ER.[sql_handle])) as [objectid]
,(select top(1) [query_plan] from sys.dm_exec_query_plan(ER.[plan_handle])) as [QueryPlan]
,NULL as [event_info]--(select top(1) [event_info] from sys.dm_exec_input_buffer(ES.[session_id], ER.[request_id])) as [event_info]
,ER.[wait_type]
,ES.[login_time]
,ES.[host_name]
,ES.[program_name]
,cast(ER.[wait_time]/1000 as decimal(18,3)) as [wait_timeSec]
,ER.[wait_time]
,ER.[last_wait_type]
,ER.[wait_resource]
,ER.[open_transaction_count]
,ER.[open_resultset_count]
,ER.[transaction_id]
,ER.[context_info]
,ER.[estimated_completion_time]
,ER.[cpu_time]
,ER.[total_elapsed_time]
,ER.[scheduler_id]
,ER.[task_address]
,ER.[reads]
,ER.[writes]
,ER.[logical_reads]
,ER.[text_size]
,ER.[language]
,ER.[date_format]
,ER.[date_first]
,ER.[quoted_identifier]
,ER.[arithabort]
,ER.[ansi_null_dflt_on]
,ER.[ansi_defaults]
,ER.[ansi_warnings]
,ER.[ansi_padding]
,ER.[ansi_nulls]
,ER.[concat_null_yields_null]
,ER.[transaction_isolation_level]
,ER.[lock_timeout]
,ER.[deadlock_priority]
,ER.[row_count]
,ER.[prev_error]
,ER.[nest_level]
,ER.[granted_query_memory]
,ER.[executing_managed_code]
,ER.[group_id]
,ER.[query_hash]
,ER.[query_plan_hash]
,EC.[most_recent_session_id]
,EC.[connect_time]
,EC.[net_transport]
,EC.[protocol_type]
,EC.[protocol_version]
,EC.[endpoint_id]
,EC.[encrypt_option]
,EC.[auth_scheme]
,EC.[node_affinity]
,EC.[num_reads]
,EC.[num_writes]
,EC.[last_read]
,EC.[last_write]
,EC.[net_packet_size]
,EC.[client_net_address]
,EC.[client_tcp_port]
,EC.[local_net_address]
,EC.[local_tcp_port]
,EC.[parent_connection_id]
,EC.[most_recent_sql_handle]
,ES.[host_process_id]
,ES.[client_version]
,ES.[client_interface_name]
,ES.[security_id]
,ES.[login_name]
,ES.[nt_domain]
,ES.[nt_user_name]
,ES.[memory_usage]
,ES.[total_scheduled_time]
,ES.[last_request_start_time]
,ES.[last_request_end_time]
,ES.[is_user_process]
,ES.[original_security_id]
,ES.[original_login_name]
,ES.[last_successful_logon]
,ES.[last_unsuccessful_logon]
,ES.[unsuccessful_logons]
,ES.[authenticating_database_id]
,ER.[sql_handle]
,ER.[statement_start_offset]
,ER.[statement_end_offset]
,ER.[plan_handle]
,NULL as [dop]--ER.[dop]
,coalesce(ER.[database_id], ES.[database_id]) as [database_id]
,ER.[user_id]
,ER.[connection_id]
from sys.dm_exec_requests ER with(readuncommitted)
right join sys.dm_exec_sessions ES with(readuncommitted)
on ES.session_id = ER.session_id
left join sys.dm_exec_connections EC with(readuncommitted)
on EC.session_id = ES.session_id
where ER.[status] in ('suspended', 'running', 'runnable')
or exists (select top(1) 1 from sys.dm_exec_requests as ER0 where ER0.[blocking_session_id]=ES.[session_id])
Essa solicitação exibe todas as solicitações ativas e todas as solicitações que bloqueiam explicitamente solicitações ativas.
Todos esses e outros scripts úteis são implementados como representações no banco de dados SRV , que é distribuído livremente. Por exemplo, o primeiro script veio da exibição [inf]. [VBigQuery] e o segundo veio da exibição [inf]. [VRequests] .
Existem também várias soluções de terceiros para o histórico de consultas. Eu uso o Query Manager do Dbeaver : e o Query Execution History do SQL Tools , incorporado no SSMS :
Esse recurso não existe imediatamente no SSMS.
Se você estiver usando o SSMS 18 ou mais recente, tente o SSMSPlus.
Possui um recurso de histórico de consultas.
https://github.com/akarzazi/SSMSPlus
Disclaimer: Eu sou o autor.
Se as consultas nas quais você está interessado são dinâmicas e falham intermitentemente, você pode registrar o SQL e a data e hora do usuário em uma tabela no momento em que a instrução dinâmica é criada. Isso seria feito caso a caso, pois requer programação específica e leva um tempo de processamento extra, assim como somente nas poucas consultas com as quais você está mais preocupado. Mas ter um registro das instruções específicas executadas pode realmente ajudar quando você está tentando descobrir por que ela falha apenas uma vez por mês. As consultas dinâmicas são difíceis de testar completamente e, às vezes, você obtém um valor de entrada específico que simplesmente não funciona e fazer esse log no momento em que o SQL é criado geralmente é a melhor maneira de ver o que especificamente não estava no sql que foi criado.
Um método ligeiramente pronto para uso seria criar uma solução no AutoHotKey. Eu uso isso, e não é perfeito, mas funciona e é gratuito. Essencialmente, esse script atribui uma tecla de atalho a CTRL+ SHIFT+, Rque copia o SQL selecionado no SSMS ( CTRL+ C), salva um arquivo SQL de carimbo de data e, em seguida, executa a consulta destacada ( F5). Se você não está acostumado com scripts AHK, o ponto e vírgula inicial é um comentário.
;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
As maiores limitações são que esse script não funcionará se você clicar em "Executar" em vez de usar o atalho de teclado, e esse script não salvará todo o arquivo - apenas o texto selecionado. Mas você sempre pode modificar o script para executar a consulta e selecionar tudo ( CTRL+ A) antes da cópia / salvar.
O uso de um editor moderno com recursos "localização em arquivos" permitirá pesquisar seu histórico SQL. Você pode até gostar e juntar seus arquivos em um banco de dados SQLite3 para consultar suas consultas.