Sorgu geçmişi bazı günlük dosyalarında mı saklanıyor? Cevabınız evet ise, yerlerini nasıl bulacağınızı söyleyebilir misiniz? Değilse, bana nasıl göreceğine dair bir tavsiye verebilir misin?
Sorgu geçmişi bazı günlük dosyalarında mı saklanıyor? Cevabınız evet ise, yerlerini nasıl bulacağınızı söyleyebilir misiniz? Değilse, bana nasıl göreceğine dair bir tavsiye verebilir misin?
Yanıtlar:
[ Bu soru muhtemelen bir kopya olarak kapatılacağından.]
SQL Server yeniden başlatılmamışsa (ve plan çıkartılmamışsa vb.), Sorguyu plan önbelleğinde bulabilirsiniz.
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 çöktüğü için dosyayı kaybettiyseniz, kurtarma dosyalarını burada bulabilirsiniz:
C:\Users\<you>\Documents\SQL Server Management Studio\Backup Files\
Aksi takdirde, sorgu geçmişinizi kaydetmenize yardımcı olması için Ed Harper'ın cevabında belirtildiği gibi SSMS Araçları Paketi gibi başka bir şey kullanmanız gerekir - ancak SQL Server 2012 ve sonraki sürümlerde ücretsiz değildir. Veya oturum açma adınıza veya ana bilgisayar adınıza filtre uygulanmış hafif bir izleme ayarlayabilirsiniz (ancak bunun için lütfen Profiler yerine sunucu tarafı izleme kullanın).
@ Nenad-Zivkovic'in yorumladığı gibi, katılmak sys.dm_exec_query_stats
ve sipariş vermek yardımcı olabilir 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
last_execution_time
Sonuncusu ama daha fazla ayrıntı eklediğinden umarım faydalı…
Varsayılan olarak SSMS'de yürütülen sorguları görmenin bir yolu yoktur. Gerçi birkaç seçenek var.
İşlem günlüğünü okuma - bu, kolay bir şey değildir, çünkü tescilli biçimindedir. Ancak, tarihsel olarak (SELECT hariç) yürütülen sorguları görmeniz gerekiyorsa, bu tek yoldur.
Bunun için ApexSQL Log ve SQL Log Rescue gibi üçüncü taraf araçlarını kullanabilirsiniz (sadece ücretsiz ancak SQL 2000). Daha fazla ayrıntı için bu konuyu inceleyin SQL Server Transaction Log Explorer / Analyzer
SQL Server profiler - sadece denetlemeye başlamak istiyorsanız ve daha önce ne olduğuyla ilgilenmiyorsanız en uygunudur. Yalnızca ihtiyacınız olan işlemleri seçmek için filtreler kullandığınızdan emin olun. Aksi takdirde çok hızlı bir şekilde ton veri elde edersiniz.
SQL Server izleme - komutların tümünü veya çoğunu yakalamak ve daha sonra ayrıştırılabilen izleme dosyasında tutmak istiyorsanız en uygunudur.
Tetikleyiciler - DML'yi (select hariç) yakalamak ve bunları veritabanında bir yerde saklamak istiyorsanız en uygunudur
SSMS araç paketi , diğer şeylerin yanı sıra yürütme geçmişini kaydetmek için işlevsellik ekler.
Diğerlerinin de belirttiği gibi, SQL Profiler'ı kullanabilirsiniz, ancak sp_trace_ * sistem saklı yordamları aracılığıyla işlevselliğinden de yararlanabilirsiniz. Örneğin, bu SQL snippet'i (en azından 2000'de; SQL 2008 için aynı olduğunu düşünüyorum, ancak iki kez kontrol etmeniz gerekecek) 10 saniyeden fazla süren tüm sorgular için yakalama RPC:Completed
ve SQL:BatchCompleted
olaylar SQL profiler'da daha sonraki bir tarihte açabileceğiniz bir izleme dosyası:
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
Her bir izleme etkinliği, sütun, vb. İçin kimliği Çevrimiçi Kitaplar'da bulabilirsiniz; sadece sp_trace_create , sp_trace_setevent ve sp_trace_setfiler sprocslarını arayın . Daha sonra izi aşağıdaki gibi kontrol edebilirsiniz:
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
... burada '15' izleme kimliğidir (yukarıdaki ilk betiğin başlattığı sp_trace_create tarafından bildirildiği gibi).
Hangi izlerin çalıştığını kontrol edebilirsiniz:
select * from ::fn_trace_getinfo(default)
Dikkatle söyleyeceğim tek şey - bunun sisteminize ne kadar yük koyacağını bilmiyorum; bazı ekler, ancak "bazı" nın ne kadar büyük olduğu muhtemelen sunucunuzun ne kadar meşgul olduğuna bağlıdır.
İzleme profiler etkin olmayan bir SQL sunucusunda uygulama etkinliği izlemek için aşağıdaki sorguyu kullanın. Yöntem, DMV'ler yerine Sorgu Deposu'nu (SQL Server 2016+) kullanır. Bu, geçmiş verilere bakmak ve daha hızlı arama yapmak için daha iyi bir yetenek sağlar. Sp_who / sp_whoisactive tarafından yakalanamayan kısa çalışan sorguları yakalamak çok etkilidir.
/* 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
Bu size bir sorgunun çalıştırıldığı saati ve tarihi göstermelidir
İhtiyacınız varsa SQL sorgularını SQL Profiler ile izleyebilirsiniz
Sorgu geçmişi sistem görünümleri kullanılarak görüntülenebilir:
Örneğin, aşağıdaki sorguyu kullanarak:
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%'
Mevcut çalışan sorgular aşağıdaki komut dosyası kullanılarak görülebilir:
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])
Bu istek, tüm etkin istekleri ve etkin istekleri açıkça engelleyen tüm istekleri görüntüler.
Tüm bu ve diğer yararlı komut dosyaları, serbestçe dağıtılan SRV veritabanında temsil olarak uygulanır . Örneğin, birinci komut görünümünde gelen [inf]. [VBigQuery] ve ikinci bir görünümünde gelen [inf]. [VRequests] .
Sorgu geçmişi için çeşitli üçüncü taraf çözümleri de vardır. Kullandığım Sorgu Müdürü dan DBeaver : ve Sorgu Yürütme Geçmiş gelen SQL Araçları gömülüdür, SSMS :
Bu özellik SSMS'deki kutudan çıkmaz.
SSMS 18 veya daha yenisini kullanıyorsanız, SSMSPlus'ı denemek isteyebilirsiniz.
Bir sorgu geçmişi özelliği vardır.
https://github.com/akarzazi/SSMSPlus
Feragatname: Ben yazarım.
İlgilendiğiniz sorgular aralıklı olarak başarısız olan dinamik sorgularsa, SQL deyimini ve datetime ve kullanıcıyı dinamik deyimin oluşturulduğu sırada bir tabloya kaydedebilirsiniz. Belirli bir programlamanın gerçekleşmesini gerektirdiğinden ve küçük bir ekstra işlem süresi gerektirdiğinden, duruma göre yapılacaktır, bu yüzden yalnızca en çok endişe duyduğunuz birkaç sorgu için yapın. Ancak, belirli ifadelerin bir günlüğünün çalıştırılması, neden yalnızca ayda bir kez başarısız olduğunu bulmaya çalışırken gerçekten yardımcı olabilir. Dinamik sorguları iyice test etmek zordur ve bazen işe yaramayacak belirli bir giriş değeri alırsınız ve SQL oluşturulduğu sırada bu günlük kaydını yapmak genellikle inşa edilen sql'de neyin özel olduğunu görmenin en iyi yoludur.
AutoHotKey'de bir çözüm oluşturmak için biraz hazır bir yöntem olacaktır. Bunu kullanıyorum ve mükemmel değil, ama çalışıyor ve ücretsiz. Temel olarak, bu komut dosyası CTRL+ SHIFT+ R'ya bir seçili SQL'i SSMS ( CTRL+ C) içine kopyalayacak, bir tarih damgası SQL dosyasını kaydedecek ve ardından vurgulanan sorguyu ( F5) çalıştıracak bir kısayol tuşu atar . AHK komut dosyalarına alışkın değilseniz, baştaki noktalı virgül bir yorumdur.
;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
En büyük sınırlamalar, klavye kısayolunu kullanmak yerine "Yürüt" e tıklarsanız bu komut dosyasının çalışmayacağı ve bu komut dosyasının tüm dosyayı (yalnızca seçilen metni) kurtaramayacağıdır. Ancak, sorguyu yürütmek için komut dosyasını her zaman değiştirebilir ve ardından kopyalama / kaydetmeden önce tümünü ( CTRL+ A) seçebilirsiniz .
"Dosyalarda bul" özelliklerine sahip modern bir düzenleyici kullanarak SQL geçmişinizde arama yapabilirsiniz. Hatta fantezi olsun ve sorgularınızı sorgulamak için dosyalarınızı bir SQLite3 veritabanına sıyırmak.