Néhány aspektus az MS SQL Server monitorozásáról. Javaslatok a nyomkövetési flagok beállítására

Bevezető

Gyakran a felhasználók, fejlesztők és MS SQL Server adatbáziskezelő rendszerek adminisztrátorai teljesítményproblémákkal találkoznak az adatbázisok vagy az adatbáziskezelő rendszerek esetében. Éppen ezért a MS SQL Server monitorozása rendkívül aktuális téma.
Ez a cikk kiegészítése egy másik cikknek. A Zabbix használata az MS SQL Server adatbázis nyomon követésére A cikkben az MS SQL Server monitorozásának néhány aspektusát fogjuk megvizsgálni, különös figyelmet fordítva arra, hogyan lehet gyorsan meghatározni, hogy mely erőforrások hiányoznak, valamint ajánlásokat adunk a nyomozási flagok beállítására.
A következő szkriptek működéséhez létre kell hozni az inf sémát a szükséges adatbázisban az alábbi módon:
inf séma létrehozása

use ;
go
create schema inf;

A memóriahiány megállapításának módszere

Az első jel, hogy memóriahiány lép fel, az az, amikor az MS SQL Server példány az összes számára rendelkezésre álló RAM-ot használja.
Ehhez létrehozzuk a következő nézetet: inf.vRAM:
inf.vRAM nézet létrehozása

CREATE view [inf].[vRAM] as
select a.[TotalAvailOSRam_Mb]						-- mennyi szabad RAM van a szerveren MB-ban
		 , a.[RAM_Avail_Percent]					-- a szabad RAM százalékos aránya a szerveren
		 , a.[Server_physical_memory_Mb]				-- összes RAM a szerveren MB-ban
		 , a.[SQL_server_committed_target_Mb]			-- összes RAM, amelyet az MS SQL Server kapott MB-ban
		 , a.[SQL_server_physical_memory_in_use_Mb] 		-- az MS SQL Server által jelenleg használt összes RAM MB-ban
		 , a.[SQL_RAM_Avail_Percent]				-- a szabad RAM százalékos aránya az MS SQL Server számára, a teljesen rendelkezésre álló RAM-ra vonatkoztatva
		 , a.[StateMemorySQL]						-- elegendő-e RAM az MS SQL Server számára
		 , a.[SQL_RAM_Reserve_Percent]				-- az MS SQL Server számára fenntartott RAM százalékos aránya a szerver teljes RAM-jához képest
		 -- elegendő-e RAM a szerverhez
		, (case when a.[RAM_Avail_Percent]5 and a.[TotalAvailOSRam_Mb]<8192 then 'Figyelmeztetés' when a.[RAM_Avail_Percent]<=5 and a.[TotalAvailOSRam_Mb]<2048 then 'Veszély' else 'Normális' end) as [StateMemoryServer]
	from
	(
		select cast(a0.available_physical_memory_kb/1024.0 as int) as TotalAvailOSRam_Mb
			 , cast((a0.available_physical_memory_kb/casT(a0.total_physical_memory_kb as float))*100 as numeric(5,2)) as [RAM_Avail_Percent]
			 , a0.system_low_memory_signal_state
			 , ceiling(b.physical_memory_kb/1024.0) as [Server_physical_memory_Mb]
			 , ceiling(b.committed_target_kb/1024.0) as [SQL_server_committed_target_Mb]
			 , ceiling(a.physical_memory_in_use_kb/1024.0) as [SQL_server_physical_memory_in_use_Mb]
			 , cast(((b.committed_target_kb-a.physical_memory_in_use_kb)/casT(b.committed_target_kb as float))*100 as numeric(5,2)) as [SQL_RAM_Avail_Percent]
			 , cast((b.committed_target_kb/casT(a0.total_physical_memory_kb as float))*100 as numeric(5,2)) as [SQL_RAM_Reserve_Percent]
			 , (case when (ceiling(b.committed_target_kb/1024.0)-1024)<ceiling(a.physical_memory_in_use_kb/1024.0) then 'Figyelmeztetés' else 'Normális' end) as [StateMemorySQL]
		from sys.dm_os_sys_memory as a0
		cross join sys.dm_os_process_memory as a
		cross join sys.dm_os_sys_info as b
		cross join sys.dm_os_sys_memory as v
	) as a;

Ezután megállapítható, hogy az MS SQL Server példány az összes neki rendelhető memóriát felhasználja, ha a következő lekérdezést futtatjuk:

select  SQL_server_physical_memory_in_use_Mb,  SQL_server_committed_target_Mb
from [inf].[vRAM];

Ha az SQL_server_physical_memory_in_use_Mb mutató folyamatosan nem kevesebb, mint az SQL_server_committed_target_Mb, akkor ellenőrizni kell a várakozási statisztikákat.
A memóriahiány meghatározásához a várakozási statisztikák alapján létrehozunk egy nézetet az inf.vWaits alapján:
Az inf.vWaits nézet létrehozása

CREATE view [inf].[vWaits] as
WITH [Waits] AS
    (SELECT
        [wait_type], --a várakozási típus neve
        [wait_time_ms] / 1000.0 AS [WaitS],--Az adott típusú várakozás összes ideje milliszekundumban. Ez az idő tartalmazza a signal_wait_time_ms-t
        ([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS],--Az adott típusú várakozás összes ideje milliszekundumban signal_wait_time_ms nélkül
        [signal_wait_time_ms] / 1000.0 AS [SignalS],--A várakozó szál jelzési ideje és végrehajtásának kezdeti ideje közötti különbség
        [waiting_tasks_count] AS [WaitCount],--Az adott típusú várakozások száma. Ez a számláló minden egyes várakozás kezdetekor növekszik
        100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [Percentage],
        ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum]
    FROM sys.dm_os_wait_stats
    WHERE [waiting_tasks_count]>0
		and [wait_type] NOT IN (
        N'BROKER_EVENTHANDLER',         N'BROKER_RECEIVE_WAITFOR',
        N'BROKER_TASK_STOP',            N'BROKER_TO_FLUSH',
        N'BROKER_TRANSMITTER',          N'CHECKPOINT_QUEUE',
        N'CHKPT',                       N'CLR_AUTO_EVENT',
        N'CLR_MANUAL_EVENT',            N'CLR_SEMAPHORE',
        N'DBMIRROR_DBM_EVENT',          N'DBMIRROR_EVENTS_QUEUE',
        N'DBMIRROR_WORKER_QUEUE',       N'DBMIRRORING_CMD',
        N'DIRTY_PAGE_POLL',             N'DISPATCHER_QUEUE_SEMAPHORE',
        N'EXECSYNC',                    N'FSAGENT',
        N'FT_IFTS_SCHEDULER_IDLE_WAIT', N'FT_IFTSHC_MUTEX',
        N'HADR_CLUSAPI_CALL',           N'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
        N'HADR_LOGCAPTURE_WAIT',        N'HADR_NOTIFICATION_DEQUEUE',
        N'HADR_TIMER_TASK',             N'HADR_WORK_QUEUE',
        N'KSOURCE_WAKEUP',              N'LAZYWRITER_SLEEP',
        N'LOGMGR_QUEUE',                N'ONDEMAND_TASK_QUEUE',
        N'PWAIT_ALL_COMPONENTS_INITIALIZED',
        N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP',
        N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP',
        N'REQUEST_FOR_DEADLOCK_SEARCH', N'RESOURCE_QUEUE',
        N'SERVER_IDLE_CHECK',           N'SLEEP_BPOOL_FLUSH',
        N'SLEEP_DBSTARTUP',             N'SLEEP_DCOMSTARTUP',
        N'SLEEP_MASTERDBREADY',         N'SLEEP_MASTERMDREADY',
        N'SLEEP_MASTERUPGRADED',        N'SLEEP_MSDBSTARTUP',
        N'SLEEP_SYSTEMTASK',            N'SLEEP_TASK',
        N'SLEEP_TEMPDBSTARTUP',         N'SNI_HTTP_ACCEPT',
        N'SP_SERVER_DIAGNOSTICS_SLEEP', N'SQLTRACE_BUFFER_FLUSH',
        N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
        N'SQLTRACE_WAIT_ENTRIES',       N'WAIT_FOR_RESULTS',
        N'WAITFOR',                     N'WAITFOR_TASKSHUTDOWN',
        N'WAIT_XTP_HOST_WAIT',          N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG',
        N'WAIT_XTP_CKPT_CLOSE',         N'XE_DISPATCHER_JOIN',
        N'XE_DISPATCHER_WAIT',          N'XE_TIMER_EVENT')
    )
, ress as (
	SELECT
	    [W1].[wait_type] AS [WaitType],
	    CAST ([W1].[WaitS] AS DECIMAL (16, 2)) AS [Wait_S],--Az adott típusú várakozás összes ideje milliszekundumban. Ez az idő tartalmazza a signal_wait_time_ms-t
	    CAST ([W1].[ResourceS] AS DECIMAL (16, 2)) AS [Resource_S],--Az adott típusú várakozás összes ideje milliszekundumban signal_wait_time_ms nélkül
	    CAST ([W1].[SignalS] AS DECIMAL (16, 2)) AS [Signal_S],--A várakozó szál jelzési ideje és végrehajtásának kezdeti ideje közötti különbség
	    [W1].[WaitCount] AS [WaitCount],--Az adott típusú várakozások száma. Ez a számláló minden egyes várakozás kezdetekor növekszik
	    CAST ([W1].[Percentage] AS DECIMAL (5, 2)) AS [Percentage],
	    CAST (([W1].[WaitS] / [W1].[WaitCount]) AS DECIMAL (16, 4)) AS [AvgWait_S],
	    CAST (([W1].[ResourceS] / [W1].[WaitCount]) AS DECIMAL (16, 4)) AS [AvgRes_S],
	    CAST (([W1].[SignalS] / [W1].[WaitCount]) AS DECIMAL (16, 4)) AS [AvgSig_S]
	FROM [Waits] AS [W1]
	INNER JOIN [Waits] AS [W2]
	    ON [W2].[RowNum] <= [W1].[RowNum]
	GROUP BY [W1].[RowNum], [W1].[wait_type], [W1].[WaitS],
	    [W1].[ResourceS], [W1].[SignalS], [W1].[WaitCount], [W1].[Percentage]
	HAVING SUM ([W2].[Percentage]) - [W1].[Percentage] < 95 -- százalékos küszöb
)
SELECT [WaitType]
      ,MAX([Wait_S]) as [Wait_S]
      ,MAX([Resource_S]) as [Resource_S]
      ,MAX([Signal_S]) as [Signal_S]
      ,MAX([WaitCount]) as [WaitCount]
      ,MAX([Percentage]) as [Percentage]
      ,MAX([AvgWait_S]) as [AvgWait_S]
      ,MAX([AvgRes_S]) as [AvgRes_S]
      ,MAX([AvgSig_S]) as [AvgSig_S]
  FROM ress
  group by [WaitType];

Ebben az esetben a memóriahiányt a következő lekérdezéssel lehet meghatározni:

SELECT [Percentage] 
      ,[AvgWait_S] 
  FROM [inf].[vWaits] 
  where [WaitType] in (
    'PAGEIOLATCH_XX',
    'RESOURCE_SEMAPHORE',
    'RESOURCE_SEMAPHORE_QUERY_COMPILE'
  );

Itt a Percentage és AvgWait_S mutatókra kell figyelni. Ha ezek összességében jelentősen magasak, akkor nagy a valószínűsége annak, hogy az MS SQL Server példánynak nem áll rendelkezésére elegendő memória. A jelentős értékek egyediek minden rendszerre. Azonban a következő mutatókkal érdemes kezdeni: Percentage>=1 és AvgWait_S>=0.005.
A mutatók megjelenítéséhez a megfigyelő rendszerben (például Zabbix) az alábbi két lekérdezést lehet létrehozni:

  1. hány százalékot képviselnek a memória használatra várakozó típusok (összeg az összes ilyen várakozási típus számára):
    select coalesce(sum([Percentage]), 0.00) as [Percentage] 
    from [inf].[vWaits] 
           where [WaitType] in (
                'PAGEIOLATCH_XX',
                'RESOURCE_SEMAPHORE',
                'RESOURCE_SEMAPHORE_QUERY_COMPILE'
      );
    
  2. hány milliszekundumot képviselnek a memória használatra várakozó típusok (a legnagyobb érték az összes ilyen várakozási típus átlagos késleltetései közül):
    select coalesce(max([AvgWait_S])*1000, 0.00) as [AvgWait_MS] 
    from [inf].[vWaits] 
           where [WaitType] in (
                'PAGEIOLATCH_XX',
                'RESOURCE_SEMAPHORE',
                'RESOURCE_SEMAPHORE_QUERY_COMPILE'
      );
    

A két mutató alapján kapott értékek dinamikájából arra lehet következtetni, hogy elegendő-e a memória az MS SQL Server példány számára.

A CPU túlterheltségének azonosítási módszere

A processzori idő hiányának megállapításához elegendő a sys.dm_os_schedulers rendszer megjelenítést használni. Itt, ha a runnable_tasks_count mutató folyamatosan 1-nél nagyobb, akkor valószínű, hogy a magok száma nem elegendő az MS SQL Server példány számára.
A megfigyelő rendszerbe (például Zabbix) való mutató megjelenítéséhez az alábbi lekérdezést lehet létrehozni:

select max([runnable_tasks_count]) as [runnable_tasks_count] 
from sys.dm_os_schedulers 
where scheduler_id<255;

A kapott értékek dinamikájából arra lehet következtetni, hogy elegendő-e a processzori idő (a CPU magok száma) az MS SQL Server példány számára.
Fontos azonban emlékezni arra, hogy a lekérdezések egyszerre több szálat is kérhetnek. Néha az optimalizáló nem tudja helyesen értékelni a lekérdezés bonyolultságát. Ilyenkor a lekérdezéshez túl sok szál kerülhet hozzárendelésre, amelyet a jelenlegi időpontban nem lehet egyidejűleg feldolgozni. Ez is várakozási típust okoz, amely a processzortime hiányával kapcsolatos, és a várakozási sorok növekedését eredményezi, amelyeket a konkrét CPU magok használnak, tehát a runnable_tasks_count ebben az esetben növekedni fog.
Ilyen esetben, mielőtt növelné a CPU-magok számát, először helyesen be kell állítani a párhuzamosság tulajdonságait az MS SQL Server példányában, valamint a 2016-os verzióktól kezdve helyesen kell beállítani az érintett adatbázisok párhuzamossági tulajdonságait:
Néhány aspektus az MS SQL Server monitorozásáról. Javaslatok a nyomkövetési flagok beállítására

Néhány aspektus az MS SQL Server monitorozásáról. Javaslatok a nyomkövetési flagok beállítására
Itt érdemes figyelni a következő paraméterekre:

  1. Max Degree of Parallelism - maximális számú szálat ad meg, amelyek egy lekérdezéshez hozzárendelhetők (alapértelmezés szerint 0 - csak az operációs rendszer és az MS SQL Server kiadása korlátozza)
  2. Cost Threshold for Parallelism - a párhuzamosság becsült költsége (alapértelmezés szerint 5)
  3. Max DOP - maximális számú szálat ad meg, amelyek egy lekérdezéshez hozzárendelhetők az adatbázis szintjén (de nem haladhatja meg a „Max Degree of Parallelism” tulajdonság értékét) (alapértelmezés szerint 0 - csak az operációs rendszer és az MS SQL Server kiadása korlátozza, valamint a teljes MS SQL Server példány „Max Degree of Parallelism” tulajdonságának korlátozása)

Itt nem lehetséges minden esetben egyformán jó receptet adni, tehát elemezni kell a nehéz lekérdezéseket.
Saját tapasztalataim alapján ajánlom a következő lépéseket OLTP rendszerek párhuzamossági tulajdonságainak beállításához:

  1. először tiltsa le a párhuzamosságot, és állítsa be az egész példány szintjén a Max Degree of Parallelism értékét 1-re
  2. elemezze a legnehezebb lekérdezéseket, és válassza ki számukra az optimális szálak számát
  3. állítsa be a Max Degree of Parallelism értékét a 2. pontban meghatározott optimalizált szálak számára, valamint a konkrét adatbázisoknak állítsa be a Max DOP értékét, amely a 2. pontból származik, minden egyes adatbázisra
  4. elemezze a legnehezebb lekérdezéseket, és azonosítsa a párhuzamosság negatív hatását. Ha van ilyen, emelje meg a Cost Threshold for Parallelism értékét.
    Ilyen rendszerek esetén, mint az 1C, a Microsoft CRM és a Microsoft NAV, a párhuzamosság letiltása a legtöbb esetben megfelelő.

Ha Standard kiadás van, a legtöbb esetben elegendő a párhuzamosság letiltása, mivel ez a kiadás korlátozott a CPU magok számában.
OLAP-rendszerekhez a fent leírt algoritmus nem alkalmas.
Saját tapasztalataim alapján javaslom a következő cselekvési algoritmust OLAP-rendszerek számára a párhuzamossági tulajdonságok beállításához:

  1. elemezze a legnehezebb lekérdezéseket, és válassza ki számukra az optimális szálak számát
  2. állítsuk be a Max Degree of Parallelism értékét az 1. pontból kapott optimalizált szálak számára, valamint a konkrét adatbázisok esetében állítsuk be a Max DOP értékét az 1. pontban kapott adatbázisonkénti értékre
  3. elemezzük a legnehezebb lekérdezéseket, és azonosítsuk a párhuzamosság korlátozásának negatív hatását. Ha van, csökkentsük a Cost Threshold for Parallelism értékét, vagy ismételjük meg a 1-2 lépéseket ennek az algoritmusnak

Tehát az OLTP-rendszerek esetében az egy szálú megoldás felé haladunk, míg OLAP-rendszerek esetében éppen ellenkezőleg: a párhuzamos feladatokból az egy szálú feladatok felé. Így optimalizálhatók a párhuzamossági beállítások mind a konkrét adatbázis, mind a teljes MS SQL Server példány számára.
Fontos megérteni, hogy a párhuzamossági beállítások idővel változtatásra szorulnak, a MS SQL Server teljesítménymonitoringának eredményei alapján.

Ajánlások a nyomkövetési flagok beállításához

Saját tapasztalat és kollégáim tapasztalatai alapján az MS SQL Server szolgáltatás indítási szintjén a 2008-2016 verziókhoz a következő nyomkövetési flagokat javaslom:

  1. 610 — Csökkenti a bejegyzések naplózását indexelt táblákban. Segíthet a nagyszámú rekorddal rendelkező táblákra történő bejegyzések kezelésében, különösen a WRITELOG hosszú várakozásaival járó tranzakciók esetén.
  2. 1117 — Ha egy fájl a fájlcsoportban megfelel az automatikus növelési küszöb követelményeinek, akkor minden fájl a fájlcsoportban növekszik.
  3. 1118 — Kötelezővé teszi, hogy minden objektum külön kiterjedéseken helyezkedjen el (kevert kiterjedések tilalma), ez minimalizálja a SGAM oldal beolvasásának szükségességét, amely a kevert kiterjedések nyomon követésére szolgál.
  4. 1224 — Kikapcsolja a zárolások nagyságának növelését a zárolások száma alapján. Azonban a memória túl aktív használata nagyságnövelést okozhat.
  5. 2371 — Megváltoztatja a statisztikák rögzített automatikus frissítési küszöbértékét dinamikus automatikus frissítési küszöbértékre. Fontos a lekérdezési tervek frissítéséhez nagy táblák esetén, ahol a rekordok számának helytelen meghatározása hibás végrehajtási terveket eredményez.
  6. 3226 — Elnyomja a sikeres biztonsági mentés végrehajtásáról szóló üzeneteket a hibajegyzékben.
  7. 4199 — Bekapcsolja a lekérdezésoptimalizálóban a kumulatív frissítési csomagok és a SQL Server frissítési csomagok kiadásaiban megvalósított módosításokat.
  8. 6532-6534 — Aktiválja a térbeli adattípusokkal végzett lekérdezések teljesítményének javítását.
  9. 8048 — Átkonvertálja a NUMA szerint szegmentált memóriatárgyakat CP szerint szegmentáltra.
  10. 8780 — További időt engedélyez a lekérdezési tervek előállításához. Néhány lekérdezés ezen zászló nélkül elutasításra kerülhet, mivel nem rendelkezik lekérdezési tervvel (nagyon ritka hiba).
  11. 8780 — 9389 — További dinamikusan biztosított memória-tárhelyet aktivál a kötegelt üzemmódú operátorok számára, lehetővé téve ezzel a kötegelt üzemmódú operátor számára, hogy további memóriát kérjen, és elkerülje az adatok átvitelét a tempdb-be, ha további memória rendelkezésre áll.

2016 előtti verziók számára érdemes aktiválni a 2301-es nyomkövetési zászlót, amely magában foglalja a kibővített döntéstámogatás optimalizációját, ezáltal segítve a megfelelőbb lekérdezési tervek kiválasztását. 2016-tól azonban gyakran negatív hatással bír a lekérdezések összesített végrehajtási idejére.
Továbbá, olyan rendszerek esetén, amelyekben sok index található (például 1C adatbázisok), javaslom a 2330-as nyomkövetési zászló aktiválását, amely letiltja az indexhasználati adatok gyűjtését, ami összességében pozitívan hat a rendszerre.
A nyomkövetési zászlókról részletesebben tájékozódhat. itt
A fenti linken fontos figyelembe venni a MS SQL Server verzióit és kiadásait, mivel az újabb verziók esetén egyes nyomkövetési zászlók alapértelmezés szerint aktiválva vannak, vagy nincsenek hatással.
A nyomkövetési zászlókat a DBCC TRACEON és a DBCC TRACEOFF parancsok segítségével lehet aktiválni és deaktiválni. Részletesebben itt olvashat. itt
A nyomkövetési zászlók állapotát a DBCC TRACESTATUS parancs segítségével lehet lekérdezni. több részletért
Ahhoz, hogy a nyomkövetési flagok automatikusan elinduljanak az MS SQL Server szolgáltatásban, meg kell nyitni a SQL Server Configuration Manager-t, és a szolgáltatás tulajdonságai között hozzá kell adni a nyomkövetési flagokat -T: formátumban.
Néhány aspektus az MS SQL Server monitorozásáról. Javaslatok a nyomkövetési flagok beállítására

Összegzés

Ebben a cikkben a MS SQL Server monitorozásának néhány aspektusát tárgyaltuk, amelyek segítségével gyorsan azonosíthatók a RAM és a CPU szabadidő hiányosságai, valamint számos egyéb, kevésbé nyilvánvaló probléma. A leggyakrabban használt nyomkövetési flagok kerültek bemutatásra.

Források:

» SQL Server várakozási statisztikái
» SQL Server várakozási statisztikái, vagy kérlek, mondd meg, hol fáj.
» A sys.dm_os_schedulers rendszer nézet
» A Zabbix használata az MS SQL Server adatbázis nyomon követésére
» SQL életstílus
» Nyomkövetési flagok
» sql.ru

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster