## Kedy použiť Keď niekto hlási „server bol ráno pomalý“ a nemáš monitoring, alebo pri vysokom CPU potrebuješ rýchlo zistiť, či CPU berie **SQL Server, alebo niečo iné** na tom istom stroji (antivírus, zálohovací agent, iná inštancia, SSIS, SSRS). ## Ako čítať výsledok Prvá sada je súhrn (priemer a maximum za poslednú hodinu a za celé okno), druhá minútové vzorky od najnovšej. `sql_cpu_pct` = proces SQL Servera, `other_processes_pct` = 100 − SQL − idle, `idle_pct` = voľné CPU. Vysoké `other_processes_pct` znamená, že problém **nie je** v dotazoch – hľadaj proces v OS. Vysoké `sql_cpu_pct` → pokračuj receptom Dlho bežiace požiadavky a Top dotazy podľa CPU. > [!WARNING] > `sys.dm_os_ring_buffers` je interná, **nepodporovaná** DMV – Microsoft negarantuje jej formát do budúcna. Záznam vzniká raz za minútu a buffer drží približne 256 záznamov (~4 h), po reštarte je prázdny. Čas vzorky sa dopočítava z `ms_ticks`, je to približný lokálny čas servera. **Oprávnenia:** `VIEW SERVER STATE` (na SQL Server 2022 stačí `VIEW SERVER PERFORMANCE STATE`). **Režim:** READ ONLY · **Verzia:** SQL Server 2016 – 2022 ## Súvisiace recepty - [Dlho bežiace požiadavky – čo práve beží](script.php?id=16&s=dlho-beziace-poziadavky-co-prave-bezi) - [Top 20 dotazov podľa CPU](script.php?id=5&s=top-20-dotazov-podla-cpu) - [Wait stats – rozdiel za N sekúnd](script.php?id=49&s=wait-stats-rozdiel-za-n-sekund) - [Server je pomalý – prvých 10 minút](script.php?id=59&s=server-je-pomaly-prvych-10-minut) ## Zdroje - [SQL high CPU troubleshooting – RING_BUFFER_SCHEDULER_MONITOR (Microsoft PFE blog, archív)](https://learn.microsoft.com/en-us/archive/blogs/sql_pfe_blog/sql-high-cpu-scenario-troubleshooting-using-sys-dm_exec_query_stats-and-ring_buffer_scheduler_monitor-ring-buffer-in-sys-dm_os_ring_buffers) - [Troubleshooting using ring buffers – „NOT SUPPORTED“ (Microsoft blog, archív)](https://learn.microsoft.com/en-us/archive/blogs/dataplatform/troubleshooting-using-ring-buffers) - [sys.dm_os_sys_info](https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-sys-info-transact-sql) _Skript je staticky overený proti dokumentácii Microsoft Learn (názvy DMV, stĺpcov a hodnôt), nie spustený na živom serveri. Pred použitím na PROD ho vyskúšaj na TEST._
CPU história za posledné ~4 hodiny (ring buffer)
Minútové vzorky vyťaženia CPU za posledných ~256 minút: koľko berie SQL Server, koľko ostatné procesy a koľko je voľné. Bez agenta a bez monitoringu.
/* DeadlockCafe | CPU história za posledné ~4 hodiny (ring buffer)
Účel: Minútové vzorky vyťaženia CPU za posledných ~256 minút: koľko berie SQL Server, koľko ostatné procesy a koľko je voľné. Bez agenta a bez monitoringu.
Režim: READ ONLY | SQL Server 2016 – 2022, on-premises
*/
SET NOCOUNT ON;
DECLARE @ms_now bigint = (SELECT ms_ticks FROM sys.dm_os_sys_info);
IF OBJECT_ID(N'tempdb..#cpu') IS NOT NULL DROP TABLE #cpu;
;WITH rb AS
(
SELECT [timestamp], CONVERT(xml, record) AS rec
FROM sys.dm_os_ring_buffers
WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR'
AND record LIKE N'%<SystemHealth>%'
)
SELECT rec.value('(Record/@id)[1]', 'int') AS record_id,
-- timestamp a ms_ticks sú milisekundy od štartu počítača
DATEADD(SECOND, -CONVERT(int, (@ms_now - [timestamp]) / 1000), SYSDATETIME()) AS sample_time,
rec.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') AS sql_cpu_pct,
rec.value('(Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') AS idle_pct
INTO #cpu
FROM rb;
-- 1) súhrn
SELECT N'posledná hodina' AS okno,
COUNT(*) AS samples,
AVG(sql_cpu_pct) AS avg_sql_cpu_pct, MAX(sql_cpu_pct) AS max_sql_cpu_pct,
AVG(CASE WHEN 100 - sql_cpu_pct - idle_pct < 0 THEN 0 ELSE 100 - sql_cpu_pct - idle_pct END) AS avg_other_pct,
MAX(CASE WHEN 100 - sql_cpu_pct - idle_pct < 0 THEN 0 ELSE 100 - sql_cpu_pct - idle_pct END) AS max_other_pct
FROM #cpu
WHERE sample_time >= DATEADD(HOUR, -1, SYSDATETIME())
UNION ALL
SELECT N'celý ring buffer',
COUNT(*),
AVG(sql_cpu_pct), MAX(sql_cpu_pct),
AVG(CASE WHEN 100 - sql_cpu_pct - idle_pct < 0 THEN 0 ELSE 100 - sql_cpu_pct - idle_pct END),
MAX(CASE WHEN 100 - sql_cpu_pct - idle_pct < 0 THEN 0 ELSE 100 - sql_cpu_pct - idle_pct END)
FROM #cpu;
-- 2) minútové vzorky, najnovšie hore
SELECT TOP (256)
sample_time,
sql_cpu_pct,
CASE WHEN 100 - sql_cpu_pct - idle_pct < 0 THEN 0 ELSE 100 - sql_cpu_pct - idle_pct END AS other_processes_pct,
idle_pct,
record_id
FROM #cpu
ORDER BY record_id DESC;