A DBA should be able to review every statement SQLInsight sends to a monitored server before granting it access. "SQL Scripts/<rule-id>.sql" holds, per rule (82 built-in, 16 community), a Danish header (what and why, how C# judges the data, thresholds with config keys, severity, exact GRANTs, versions, collector file and member) and the collector's SQL verbatim, every version variant as its own batch. "_collectors/<Collector>.sql" holds each collector's queries once. The only statement that is not strictly read-only is documented in the scripts: the deadlock collector's session temp table (#system_health). Inline SQL in the collectors moved to internal constants and Build*Sql methods (no text changed), so SqlScriptTests can check that the scripts still contain the SQL the code sends, that every rule has a script, that every collector query is registered, and that nothing writes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
94 lines
6.1 KiB
Transact-SQL
94 lines
6.1 KiB
Transact-SQL
-- ===================================================================================================================
|
|
-- Collector: QueryStatsCollector ("query-stats")
|
|
-- ===================================================================================================================
|
|
-- Hvad: Top SQL: de tungeste sætninger (top 50 efter CPU, varighed, læsninger og antal) blandt dem, der har
|
|
-- kørt siden forrige måling. Ingen planer, tekst afkortet.
|
|
-- Fil: src/SQLInsight.Collectors/Performance/QueryStatsCollector.cs
|
|
-- Interval: 5 min som standard (SQLInsight:CollectorIntervals:query-stats)
|
|
-- Versioner: SQL Server 2005 og nyere
|
|
--
|
|
-- Rettigheder til agentens login (se db/permissions/grant-least-privilege.sql; [agent] = agentens login):
|
|
-- GRANT VIEW SERVER STATE TO [agent]; -- SQL Server 2005-2019
|
|
-- GRANT VIEW SERVER PERFORMANCE STATE TO [agent]; -- SQL Server 2022+ (erstatter VIEW SERVER STATE)
|
|
-- GRANT VIEW SERVER SECURITY STATE TO [agent]; -- SQL Server 2022+
|
|
--
|
|
-- Bruges af: SQLI-CPU-002
|
|
-- Read-only: Ja: kun SELECT samt SET-sessionsindstillinger. Intet ændrer data, indstillinger eller objekter.
|
|
-- Kørsel: Kør i SSMS som agentens login. Hver variant er sin egen batch (GO); en variant for en anden SQL Server-version
|
|
-- end din kan fejle - det er forventet. Agenten kører altid med sessionsindstillingerne i _collectors/InstanceProbe.sql.
|
|
-- ===================================================================================================================
|
|
|
|
-- Variant: SQL Server 2008 og nyere: starttidspunkt
|
|
-- Kilde: QueryStatsCollector.StartTimeSql(2008+)
|
|
-- Kode: src/SQLInsight.Collectors/Db.cs : Db.StartTimeSql(version)
|
|
SELECT (SELECT sqlserver_start_time FROM sys.dm_os_sys_info)
|
|
GO
|
|
|
|
-- Variant: SQL Server 2005: starttidspunkt
|
|
-- Kilde: QueryStatsCollector.StartTimeSql(2005)
|
|
-- Kode: src/SQLInsight.Collectors/Db.cs : Db.StartTimeSql(version)
|
|
SELECT (SELECT create_date FROM sys.databases WHERE database_id = 2)
|
|
GO
|
|
|
|
-- Variant: SQL Server 2008 og nyere (første kørsel: de seneste 15 minutter)
|
|
-- Kilde: QueryStatsCollector.SqlFor(2008+)
|
|
-- Kode: src/SQLInsight.Collectors/Performance/QueryStatsCollector.cs : QueryStatsCollector.Sql2008 via SqlFor(version, since: null)
|
|
WITH s AS (
|
|
SELECT qs.query_hash AS k,
|
|
SUM(qs.execution_count) AS execs, SUM(qs.total_worker_time) AS cpu, SUM(qs.total_elapsed_time) AS elapsed,
|
|
SUM(qs.total_logical_reads) AS lreads, SUM(qs.total_physical_reads) AS preads, SUM(qs.total_logical_writes) AS writes,
|
|
MIN(qs.creation_time) AS created, MAX(qs.last_execution_time) AS last_exec
|
|
FROM sys.dm_exec_query_stats qs
|
|
GROUP BY qs.query_hash
|
|
HAVING MAX(qs.last_execution_time) >= DATEADD(minute, -15, GETDATE())),
|
|
t AS (
|
|
SELECT k FROM (SELECT TOP (50) k FROM s ORDER BY cpu DESC) a
|
|
UNION SELECT k FROM (SELECT TOP (50) k FROM s ORDER BY elapsed DESC) b
|
|
UNION SELECT k FROM (SELECT TOP (50) k FROM s ORDER BY lreads DESC) c
|
|
UNION SELECT k FROM (SELECT TOP (50) k FROM s ORDER BY execs DESC) d)
|
|
SELECT CONVERT(varchar(20), s.k, 1), s.execs, s.cpu, s.elapsed, s.lreads, s.preads, s.writes, s.created, s.last_exec,
|
|
DB_NAME(COALESCE(st.dbid, pa.dbid)),
|
|
CAST(SUBSTRING(st.text, r.statement_start_offset / 2 + 1,
|
|
CASE WHEN r.statement_end_offset = -1 THEN 4000
|
|
ELSE (r.statement_end_offset - r.statement_start_offset) / 2 + 1 END) AS nvarchar(4000)),
|
|
GETDATE()
|
|
FROM s JOIN t ON t.k = s.k
|
|
OUTER APPLY (SELECT TOP (1) q.sql_handle, q.plan_handle, q.statement_start_offset, q.statement_end_offset
|
|
FROM sys.dm_exec_query_stats q WHERE q.query_hash = s.k ORDER BY q.last_execution_time DESC) r
|
|
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) st
|
|
OUTER APPLY (SELECT CAST(a.value AS int) AS dbid FROM sys.dm_exec_plan_attributes(r.plan_handle) a WHERE a.attribute = N'dbid') pa
|
|
GO
|
|
|
|
-- Variant: SQL Server 2005 (første kørsel: de seneste 15 minutter)
|
|
-- Kilde: QueryStatsCollector.SqlFor(2005)
|
|
-- Kode: src/SQLInsight.Collectors/Performance/QueryStatsCollector.cs : QueryStatsCollector.Sql2005 via SqlFor(version, since: null)
|
|
WITH s AS (
|
|
SELECT qs.sql_handle AS h, qs.statement_start_offset AS so, qs.statement_end_offset AS eo,
|
|
SUM(qs.execution_count) AS execs, SUM(qs.total_worker_time) AS cpu, SUM(qs.total_elapsed_time) AS elapsed,
|
|
SUM(qs.total_logical_reads) AS lreads, SUM(qs.total_physical_reads) AS preads, SUM(qs.total_logical_writes) AS writes,
|
|
MIN(qs.creation_time) AS created, MAX(qs.last_execution_time) AS last_exec
|
|
FROM sys.dm_exec_query_stats qs
|
|
GROUP BY qs.sql_handle, qs.statement_start_offset, qs.statement_end_offset
|
|
HAVING MAX(qs.last_execution_time) >= DATEADD(minute, -15, GETDATE())),
|
|
t AS (
|
|
SELECT h, so, eo FROM (SELECT TOP (50) h, so, eo FROM s ORDER BY cpu DESC) a
|
|
UNION SELECT h, so, eo FROM (SELECT TOP (50) h, so, eo FROM s ORDER BY elapsed DESC) b
|
|
UNION SELECT h, so, eo FROM (SELECT TOP (50) h, so, eo FROM s ORDER BY lreads DESC) c
|
|
UNION SELECT h, so, eo FROM (SELECT TOP (50) h, so, eo FROM s ORDER BY execs DESC) d)
|
|
SELECT sys.fn_varbintohexstr(s.h) + ':' + CAST(s.so AS varchar(12)) + ':' + CAST(s.eo AS varchar(12)),
|
|
s.execs, s.cpu, s.elapsed, s.lreads, s.preads, s.writes, s.created, s.last_exec,
|
|
DB_NAME(COALESCE(st.dbid, pa.dbid)),
|
|
CAST(SUBSTRING(st.text, s.so / 2 + 1, CASE WHEN s.eo = -1 THEN 4000 ELSE (s.eo - s.so) / 2 + 1 END) AS nvarchar(4000)),
|
|
GETDATE()
|
|
FROM s JOIN t ON t.h = s.h AND t.so = s.so AND t.eo = s.eo
|
|
OUTER APPLY sys.dm_exec_sql_text(s.h) st
|
|
OUTER APPLY (SELECT TOP (1) q.plan_handle FROM sys.dm_exec_query_stats q
|
|
WHERE q.sql_handle = s.h AND q.statement_start_offset = s.so AND q.statement_end_offset = s.eo) r
|
|
OUTER APPLY (SELECT CAST(a.value AS int) AS dbid FROM sys.dm_exec_plan_attributes(r.plan_handle) a WHERE a.attribute = N'dbid') pa
|
|
GO
|
|
|
|
-- Variant: Alle versioner, kun når ingen sætning har kørt siden sidst
|
|
-- Kilde: QueryStatsCollector.ServerTimeSql
|
|
-- Kode: src/SQLInsight.Collectors/Performance/QueryStatsCollector.cs : QueryStatsCollector.ServerTimeSql
|
|
SELECT GETDATE()
|
|
GO
|