Korištenje Zabbixa za praćenje baze podataka MS SQL Server

Predgovor

Često se javlja potreba da se administratoru u realnom vremenu javlja o problemima vezanim za bazu podataka.

U ovom članku biće opisano šta je potrebno postaviti u Zabbix-u za praćenje baze podataka MS SQL Server.

Napominjem da detaljna podešavanja neće biti opisana, ali će u ovom članku biti navedene formule, opšti saveti i detaljan opis kako dodati korisničke elemente podataka putem skladišnih procedura.
Takođe, ovde će biti razmotreni samo osnovni pokazatelji performansi.

Rešenje

Na početku ću opisati sve one pokazatelje performansi (preko elemenata podataka u Zabbix-u) koji su nam potrebni:

  1. Logički disk
    1. Avg Disc sec/Read
      Pokazuje prosečno vreme čitanja podataka sa diska, izraženo u sekundama. Prosečna vrednost pokazatelja performansi Avg. Disk sec/Read ne bi trebala da prelazi 10 milisekundi. Maksimalna vrednost pokazatelja performansi Avg. Disk sec/Read ne bi trebala da prelazi 50 milisekundi.

      Zabbix,: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read], a takođe je važno pratiti potreban disk, na primer, ovako: perf_counter[LogicalDisk(C:)Avg. Disk sec/Read]

      Primjeri okidača:
      {NAZIV_ČVORA:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.005, nivo-visok
      i
      {NAZIV_ČVORA:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.0025, nivo-srednji

    2. Avg Disc sec/Write
      Pokazuje prosečno vreme upisivanja podataka na disk, izraženo u sekundama. Prosečna vrednost pokazatelja performansi Avg. Disk sec/Write ne bi trebala da prelazi 10 milisekundi. Maksimalna vrednost pokazatelja performansi Avg. Disk sec/Write ne bi trebala da prelazi 50 milisekundi.

      Zabbix,: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write], a takođe je važno pratiti potreban disk, na primer, ovako: perf_counter[LogicalDisk(C:)Avg. Disk sec/Write]

      Primjeri okidača:
      {NAZIV_ČVORA:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.005, nivo-visok
      i
      {NAZIV_ČVORA:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.0025, nivo-srednji

    3. Avg Disk Queue Length

      Srednja duljina reda zahtjeva za disk. Prikazuje broj zahtjeva za diskom koji čekaju obradu tijekom određenog vremenskog intervala. Normalno je da red bude ne duži od 2 za pojedinačni disk. Ako ima više od dva zahtjeva u redu, disk je možda preopterećen i ne može obraditi dolazne zahtjeve. Možete utvrditi koje operacije disk ne može obraditi pomoću brojača Avg. Disk Read Queue Length (red zahtjeva za čitanje) i Avg. Disk Write Queue Length (red zahtjeva za pisanje).
      Vrijednost Avg. Disk Queue Length se ne mjeri, već se izračunava prema Littleovom zakonu iz matematičke teorije redova. Prema tom zakonu, broj zahtjeva koji čekaju obradu, u prosjeku, jednak je frekvenciji dolaska zahtjeva pomnoženoj s vremenom obrade zahtjeva. To jest, u našem slučaju Avg. Disk Queue Length = (Disk Transfers/sec) * (Avg. Disk sec/Transfer).

      Avg. Disk Queue Length se navodi kao jedan od glavnih brojača za određivanje opterećenosti diskovnog sustava, no za adekvatnu procjenu potrebno je točno razumjeti fizičku strukturu sustava pohrane. Na primjer, za pojedinačni tvrdi disk kritična se smatra vrijednost veća od 2, a ako je disk smješten na RAID-matrici od 4 diska, tada se treba brinuti pri vrijednosti većoj od 4*2=8.

      Zabbix,: perf_counter[LogicalDisk(_Total)Avg. Disk Queue Length], a također je važno pratiti potrebni disk, na primjer: perf_counter[LogicalDisk(C:)Avg. Disk Queue Length]

  2. Memorija
    1. Stranice/sec
      Prikazuje broj stranica koje je SQL Server učitao s diska ili zapisao na disk kako bi omogućio pristup stranicama u memoriji koje nisu bile učitane u radnu memoriju u trenutku pristupa. Ova vrijednost je zbroj vrijednosti Pages Input/sec i Pages Output/sec, a također uzima u obzir razmjenu stranica (swap) sistemske cache memorije za pristup datotečnim datotekama aplikacija. Osim toga, uključena je i razmjena ne-cacheiranih datoteka koje se izravno mapiraju u memoriju. Ovo je glavni mjerač koji treba pratiti u slučaju da se primijeti velika opterećenost korištenjem memorije i povezanog prekomjernog razmjena stranica. Ovaj mjerač karakterizira razinu razmjene i njegova normalna (ne pikna) vrijednost trebala bi biti blizu nule. Povećanje razmjene ukazuje na potrebu za povećanjem RAM-a ili smanjenjem broja aktivnih aplikacija na serveru.

      Zabbix,: perf_counter[MemoryPages/sec]
      Primjer okidača:
      {IME_NODA:perf_counter[MemoryPages/sec].min(5m)}>1000, razina-informacija

    2. Greške stranica/sec

      Ova vrijednost je mjerač pogrešaka stranica. Greška stranice nastaje kada proces referencira stranicu virtualne memorije koja nije u radnom skupu radne memorije. Ovaj mjerač uključuje i one pogreške stranica koje zahtijevaju pristup disku, kao i one koje se javljaju zbog neprisutnosti stranice u radnom skupu u radnoj memoriji. Većina procesora može obraditi pogreške stranica drugog tipa bez značajnih odgađanja. Međutim, obrada pogrešaka stranica prvog tipa, koja zahtijeva pristup disku, može dovesti do značajnih kašnjenja.

      Zabbix,: perf_counter[MemoryPage Faults/sec]
      Primjer okidača:
      {IME_NODA:perf_counter[MemoryPage Faults/sec].min(5m)}>1000, razina-informacija

    3. Dostupni bajti

      Prati količinu dostupne memorije u bajtovima za izvršavanje različitih procesa. Niske brojke označavaju nedostatak memorije. Rješenje je povećanje memorije. Ovaj mjerač u većini slučajeva trebao bi stalno biti iznad 5000 KB.
      Ima smisla ručno postaviti prag za Available Mbytes iz sljedećih razloga:

      •50% slobodne memorije dostupno = Odlično
      •25% dostupne memorije = Potrebna pažnja
      •10% slobodno = Mogući problemi
      •Manje od 5% dostupne memorije = Kritično za brzinu, potrebno je intervenirati.
      Zabbix,: perf_counter[MemoryAvailable Bytes]

  3. Procesor (Ukupno): % Vrijeme procesora
    Ovaj mjerač prikazuje postotak vremena tijekom kojeg je procesor bio zauzet obavljanjem operacija za neidle niti (non-Idle thread). Ovu vrijednost možemo smatrati udjelom vremena koji se koristi za obavljanje korisnog rada. Svakom procesoru može biti dodijeljena idle nit koja koristi neproduktivne CPU cikle koji se ne koriste od strane drugih niti. Ovaj mjerač karakteriziraju kratki vrhovi koji mogu doseći 100 posto. Međutim, ako se primijete dulje razdoblja kada je iskorištenost procesora iznad 80 posto, sustav će biti učinkovitiji s većim brojem procesora.

    Zabbix,: perf_counter[Processor(_Total)% Vrijeme procesora], također može imati ispod prikazano po jezgrama
    Primjer okidača:
    {NAZIVČVORA:perf_counter[Processor(_Total)% Vrijeme procesora].min(5m)}>80, razina-informacija

  4. Mrežni interfejs (*): % Bytes Total/sec
    Sveukupna količina poslanih i primljenih bajtova po sekundi svih interfejsa. To je propusnost interfejsa (u bajtovima). Potrebno je usporediti ovu vrijednost s maksimalnom propusnošću mrežne kartice. Općenito, ovaj mjerač ne bi trebao pokazivati više od 50% iskorištenosti propusnosti mrežnog adaptera.
    Zabbix,: perf_counter[Network Interface(*)Bytes Sent/sec]
  5. MS SQL Server: Metode pristupa
    Objekt Metode pristupa (Access Methods) u SQL Serveru pruža mjerače koji pomažu u nadzoru pristupa logičkim podacima unutar baze podataka. Fizički pristup stranicama baze podataka na disku kontrolira se pomoću mjerača upravitelja međuspremnika. Praćenje metoda pristupa podacima u bazi podataka pomaže odrediti je li moguće povećati učinkovitost upita dodatkom ili promjenom indeksa, dodavanjem ili premještanjem sekcija, dodavanjem datoteka ili skupina datoteka, defragmentacijom indeksa ili promjenom teksta upita. Također, pomoću mjerača objekta Metode pristupa može se nadzirati veličina podataka, indeksa i slobodnog prostora u bazi podataka, kontrolirajući volumene i fragmentaciju za svaki primjerak poslužitelja. Prekomjerna fragmentacija indeksa može značajno smanjiti učinkovitost.
    1. Podjela stranica/sec
      Broj dijeljenja stranica u sekundi, izvršenih uslijed preopterećenja stranica indeksa. Visoka vrijednost ovog pokazatelja implicira da SQL Server mora izvršiti veliki broj resursno intenzivnih operacija dijeljenja stranica i premještanja dijela postojeće stranice na novo mjesto prilikom izvođenja operacija umetanja i izmjene podataka. Takvim operacijama treba izbjegavati koliko god je to moguće. Problem se može pokušati riješiti na dva načina:
      — stvoriti klasterirani indeks za stupce s automatskim povećanjem. U tom slučaju, novi zapisi neće biti smješteni unutar stranica koje su već zauzete podacima, već će postupno zauzimati nove stranice;
      — rekonstruirati indekse povećanjem vrijednosti parametra Fillfactor. Ovaj parametar omogućava rezerviranje slobodnog prostora u stranicama indeksa koji će se koristiti za smještaj novih podataka, bez potrebe za obavljanjem operacija dijeljenja stranica.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCIJE:Access MethodsPage Splits/sec»,30]
      Primjer okidača: {NAZIV_NOD-a:perf_counter[«MSSQL$NAZIV_INSTANCIJE:Access MethodsPage Splits/sec»,30].last()}>{NAZIV_NOD-a:perf_counter[«MSSQL$NAZIV_INSTANCIJE:SQL StatisticsBatch Requests/sec»,30].last()}\/5, razina-informacija
    2. Full Scans\/sec
      Broj neograničenih operacija potpunog skeniranja u sekundi. Ove operacije uključuju skeniranje glavne tablice i potpuno skeniranje indeksa. Stabilno povećanje ovog pokazatelja može ukazivati na degradaciju sustava (nedostatak potrebnih indeksa, njihova velika fragmentacija, neiskorištavanje postojećih indeksa optimizatorom, prisutnost neiskorištenih indeksa). Međutim, treba napomenuti da potpuno skeniranje u malim tablicama ne mora nužno biti loše, jer ako se cijela tablica može smjestiti u RAM, tada će potpuno skeniranje biti brže. No, u većini slučajeva, stabilan rast ovog pokazatelja ukazuje na degradaciju sustava. Sve to vrijedi samo za OLTP sustave. U OLAP sustavima, stalna potpuna skeniranja su normalna.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCIJE:Access MethodsFull Scans\/sec»,30]

  6. MS SQL Server: Buffer Manager
    Objekt Buffer Manager (upravljanja baferima) pruža brojače koji omogućuju praćenje kako SQL Server koristi sljedeće resurse:
    — memoriju za pohranu stranica podataka;
    — mjerači koji služe za praćenje fizičkog ulaza-izlaza kada SQL Server čita i zapisuje stranice baza podataka;
    — proširenje međuspremnika za povećanje međuspremnika koristeći brzu neizbrisivu memoriju, kao što su SSD-ovi;
    — praćenje memorije i mjerača koje koristi SQL Server pomaže u dobivanju sljedećih informacija;
    — postoje li 'uska grla' uzrokovana nedostatkom fizičke memorije. Ako se često korišteni podaci ne mogu pohraniti u međuspremniku, SQL Server je prisiljen čitati ih s diska;
    — može li se poboljšati učinkovitost izvršenja upita povećanjem volumena memorije ili dodjeljivanjem dodatne memorije za keširanje podataka ili pohranu internih struktura SQL Servera;
    — koliko često SQL Server čita podatke s diska. U usporedbi s drugim operacijama, poput pristupa memoriji, fizički ulaz-izlaz traje duže. Smanjenje volumena ulaza-izlaza može poboljšati izvedbu izvršenja upita.
    1. Buffer Cache hit ratio
      Pokazuje u kojoj mjeri SQL Server može smjestiti podatke u međuspremnik. Što je ova vrijednost viša, to je bolje, jer za učinkovito obraćanje SQL Servera stranicama podataka, one moraju biti u međuspremniku i fizički ulaz-izlaz (I/O) ne bi trebao postojati. Ako se primijeti stalno smanjenje prosjeka ovog mjerača, potrebno je razmotriti dodavanje RAM-a. Ova vrijednost uvijek bi trebala biti iznad 90% za OLTP sustave i iznad 50% za OLAP sustave.
      Zabbix,: perf_counter[«MSSQL$IME_INSTANCE:Buffer ManagerBuffer cache hit ratio»,30]
      Primjeri okidača: {IME_NOD-a:perf_counter[«MSSQL$IME_INSTANCE:Buffer ManagerBuffer cache hit ratio»,30].last()}<70, razina-visoka
      i
      {IME_NOD-a:perf_counter[«MSSQL$IME_INSTANCE:Buffer ManagerBuffer cache hit ratio»,30].last()}<80, razina-srednja
    2. Očekivano trajanje stranice
      Prikazuje koliko dugo će stranica biti trajno pohranjena u trenutnom stanju. Ako vrijednost konstantno pada, to znači da sustav zloupotrebljava bafer, a time potencijalno može doći do problema s radom memorije koji smanjuju performanse. Vrijedi napomenuti da ne postoji univerzalna mjera ispod koje se može jednoznačno prosuditi da sustav zloupotrebljava bafer (vrijednost od 300 sekundi zastarjela je s MS SQL Server 2012).
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANSE:Buffer ManagerPage life expectancy»,30]
      Primjer okidača: {NAZIV_NODE:perf_counter[«MSSQL$NAZIV_INSTANSE:Buffer ManagerPage life expectancy»,30].last()}<5, razina-informacija

  7. MS SQL Server: Opća statistika
    Objekt Opća statistika (General Statistics) u SQL Serveru pruža brojila koja omogućuju praćenje ukupne aktivnosti poslužitelja, primjerice broj aktivnih veza i broj korisnika po sekundi koji se povezuju ili odspajaju s računala na kojem je pokrenuta instanca SQL Servera. Ove indikatore je korisno koristiti u velikim sustavima obrade transakcija (OLTP), gdje se veliki broj klijenata stalno povezuje i odspaja od instance SQL Servera.
    1. Blokirani proces
      Trenutni broj blokiranih procesa.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANSE:General StatisticsProcesses blocked»,30]
      Primjer okidača: ({NAZIV_NODE:perf_counter[«MSSQL$NAZIV_INSTANSE:General StatisticsProcesses blocked»,30].min(2m,0)}>=0)
      i ({NAZIV_NODE:perf_counter[«MSSQL$NAZIV_INSTANSE:General StatisticsProcesses blocked»,30].time(0)}>=50000)
      i ({NAZIV_NODE:perf_counter[«MSSQL$NAZIV_INSTANSE:General StatisticsProcesses blocked»,30].time(0)}<=230000), razina-informacija (ovdje je ograničenje za signalizaciju od 05:00 do 23:00)
    2. Korisničke veze
      Trenutni broj korisnika povezanih na SQL Server.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANSE:General StatisticsUser Connections»,30]

  8. MS SQL Server: Zaključavanja
    Objekt Locks (Zaključavanja) u Microsoft SQL Server pruža informacije o zaključavanjima SQL Servera koja su dodijeljena za određene vrste resursa. Zaključavanja se izdaju na resurse SQL Servera, poput redaka koji su pročitani ili izmijenjeni transakcijom, kako bi se spriječilo istovremeno korištenje resursa od strane više transakcija. Na primjer, ako transakcija dobije ekskluzivno (X) zaključavanje na redak u tablici, nijedna druga transakcija neće moći izmijeniti taj redak dok se zaključavanje ne oslobodi. Minimiziranje korištenja zaključavanja povećava paralelizam, što može poboljšati ukupnu izvedbu. Može se pratiti nekoliko instanci objekta Locks istodobno, od kojih svaka predstavlja zaključavanje različitih vrsta resursa.
    1. Prosječno vrijeme čekanja (ms)
      Prosječno vrijeme čekanja (u milisekundama) za sve zahtjeve za zaključavanje, pri čemu je bilo potrebno čekanje. Ovaj broj pokazuje koliko prosječno korisničkim procesima treba vremena da čekaju kako bi postavili zaključavanje na resurs. Maksimalna dopuštena vrijednost ovog broja u potpunosti ovisi o vašem zadatku, a teško je odrediti neku prosječnu vrijednost za sve aplikacije ovdje. Previsoka vrijednost ovog broja može značiti probleme s zaključavanjima u vašoj bazi podataka.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCIJE:Locks(_Total)Prosječno vrijeme čekanja (ms)»,30]
      Primjer okidača: {NAZIV_NOD-a:perf_counter[«MSSQL$NAZIV_INSTANCIJE:Locks(_Total)Prosječno vrijeme čekanja (ms)»,30].last()}>=500, razina-informacija
    2. Vrijeme čekanja na zaključavanje (ms)
      Ukupno vrijeme čekanja na zaključavanja (u milisekundama) u posljednjoj sekundi.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCIJE:Locks(_Total)Vrijeme čekanja na zaključavanje (ms)»,30]
    3. Zaključavanja po sekundi
      Broj slučajeva u posljednjoj sekundi kada je nit morala čekati zbog zahtjeva za zaključavanje.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCIJE:Locks(_Total)Zaključavanja po sekundi»,30]
    4. Ciklična vremena istjecanja zaključavanja po sekundi
      Broj ponavljanja kada nije moguće dobiti zaključavanje putem cikličnog pristupa. Vrijednost SQL Server konfiguracijskog parametra spin counter određuje broj «okretaja» niti (spins) prije nego što istekne vrijeme čekanja i nit postane neaktivna.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCIJE:Locks(_Total)Ciklična vremena istjecanja zaključavanja po sekundi»,30]
      Primjer okidača: {NAZIV_NOD-a:perf_counter[«MSSQL$NAZIV_INSTANCIJE:Locks(_Total)Locks(_Total)Ciklična vremena istjecanja zaključavanja po sekundi»,30].last()}>1000, razina-informacija
    5. Zahtjevi za zaključavanje po sekundi
      Broj zahtjeva u sekundi navedenog tipa zaključavanja.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCE:Locks(_Total)Lock Requests/sec»,30]
      Primjer okidača: {NAZIV_UZLA:perf_counter[«MSSQL$NAZIV_INSTANCE:Locks(_Total)Lock Requests/sec»,30].last()}>500000, nivo-informacija
    6. Broj blokada u sekundama
      Broj zahtjeva za zaključavanje u sekundi koji dovode do međusobnih blokada. Prisutnost međusobnih blokada ukazuje na pogrešno konstruirane upite koji blokiraju zajedničke resurse.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCE:Number of Deadlocks/sec»,30]
      Primjer okidača: {NAZIV_UZLA:perf_counter[«MSSQL$NAZIV_INSTANCE:Locks(_Total)Number of Deadlocks/sec»,30].last()}>1, nivo-visok

  9. MS SQL Server: Upravitelj memorije
    Objekt Upravitelj memorije u Microsoft SQL Serveru osigurava brojače za kontrolu korištenja memorije cijelog poslužitelja. Kontrola korištenja memorije poslužitelja radi procjene djelovanja korisnika i korištenja resursa može pomoći u identifikaciji nedostatka performansi. Kontrola memorije koju koristi instanca SQL Servera može pomoći u određivanju:
    — postoje li nedostaci u nedovoljnoj fizičkoj memoriji za pohranu često korištenih podataka. Ako je memorija nedostatna, SQL Server mora dobiti podatke s diska;
    — može li se performansa upita poboljšati ako se doda memorija ili poveća količina dostupne memorije za keširanje podataka ili unutarnjih struktura SQL Servera.
    1. Aktivni zahtjevi za memoriju
      Ukazuje na ukupni broj procesa koji su uspješno dobili memoriju radnog prostora. Prilikom stabilnog pada ovog pokazatelja, potrebno je povećati RAM.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCE:Memory ManagerMemory Grants Outstanding»,30]
    2. Očekivanje odobrenja memorije
      Ukazuje na ukupni broj procesa koji čekaju odobrenje radne memorije. Prilikom stabilnog rasta ovog pokazatelja, potrebno je povećati RAM.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCE:Memory ManagerMemory Grants Pending»,30]

  10. MS SQL Server: Statistika
    Objekt Statistika u Microsoft SQL Serveru osigurava rad brojača za praćenje kompilacija i tipova upita koji se šalju instanci SQL Servera. Praćenje broja kompilacija i ponovnih kompilacija upita i broja paketa koje prima instanca SQL Servera pruža uvid u to koliko brzo SQL Server izvršava upite korisnika i koliko učinkovito ih obrađuje optimizator upita.
    1. Batch Requests/sec
      Broj T-SQL komandi koje su primljene u sekundi. Na ovu statistiku utječu svi ograničujući faktori (ulazno-izlazni sustav, broj korisnika, veličina keša, složenost upita itd.). Visok broj zahtjeva paketa ukazuje na visoku propusnost.
      Zabbix,: perf_counter[«MSSQL$NAZIV_INSTANCIJE:SQL StatisticsBatch Requests/sec»,30]

Pored svega navedenog, moguće je postaviti i druge podatke (kao i kreirati okidače na njih s kasnijim obavještavanjem). Na primjer:
1) veličina slobodnog prostora na disku
2) veličine datoteka baze podataka i log datoteke
itd.
Međutim, svi ti pokazatelji ne prikazuju problem s upitima u stvarnom vremenu.
Za to je potrebno kreirati svoje specijalne brojače.
Zbog razmatranja privatnosti, neću navesti primjere takvih brojača. Osim toga, oni se podešavaju jedinstveno za svaki sustav. Ali ću istaknuti da se za sustave kao što su 1C, NAV i CRM mogu kreirati specijalizirani brojači u suradnji s odgovarajućim programerima.
Navedite primjer stvaranja općeg pokazatelja koji prikazuje koliko se upita izvršava i koliko upita čeka na izvršenje (pauzirani ili blokirani) u svakom trenutku.
Za to je potrebno kreirati pohranjenu proceduru:
Kod

USE [IME_BAZE_PODATAKA]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [nav].[ZabbixGetCountRequestStatus]
	@Status nvarchar(255)
AS
BEGIN
	

		vrati broj upita s određenim statusom
	
	SET NOCOUNT ON;

	select count(*) as [Count]
	from sys.dm_exec_requests ER with(readuncommitted)
	where [status]=@Status
END

Zatim je potrebno otići u mapu gdje se nalazi Zabbix (zabbixconfuserparams.d) i kreirati 2 datoteke s ekstenzijom ps1 (PowerShell) i napisati u svakoj od njih sljedeće kodove:
Kod za aktivne upite

$SQLServer = "NAZIV_INSTANCIJA";
$uid = "LOGIN"; 
$pwd = "LOZINKA";
$Status="running";

$connectionString = "Server = $SQLServer; Database=NAZIV_BAZE; Integrated Security = False; User ID = $uid; Password = $pwd;";

$connection = New-Object System.Data.SqlClient.SqlConnection;
$connection.ConnectionString = $connectionString;

#Stvaramo upit direktno za MSSQL
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand;
$SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure;  
$SqlCmd.CommandText = "nav.ZabbixGetCountRequestStatus";
$SqlCmd.Connection = $Connection;

$paramStatus=$SqlCmd.Parameters.Add("@Status" , [System.Data.SqlDbType]::VarChar);
$paramStatus.Value = $Status;

$connection.Open();
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter;
$SqlAdapter.SelectCommand = $SqlCmd;
$DataSet = New-Object System.Data.DataSet;
$SqlAdapter.Fill($DataSet) > $null;
$connection.Close();

$result = $DataSet.Tables[0].Rows[0]["Count"];

write-host $result;

Kod za čekajuće upite

$SQLServer = "NAZIV_INSTANCIJA";
$uid = "LOGIN"; 
$pwd = "LOZINKA";
$Status="suspended";

$connectionString = "Server = $SQLServer; Database=NAZIV_BAZE; Integrated Security = False; User ID = $uid; Password = $pwd;";

$connection = New-Object System.Data.SqlClient.SqlConnection;
$connection.ConnectionString = $connectionString;

#Stvaramo upit direktno za MSSQL
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand;
$SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure;  
$SqlCmd.CommandText = "nav.ZabbixGetCountRequestStatus";
$SqlCmd.Connection = $Connection;

$paramStatus=$SqlCmd.Parameters.Add("@Status" , [System.Data.SqlDbType]::VarChar);
$paramStatus.Value = $Status;

$connection.Open();
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter;
$SqlAdapter.SelectCommand = $SqlCmd;
$DataSet = New-Object System.Data.DataSet;
$SqlAdapter.Fill($DataSet) > $null;
$connection.Close();

$result = $DataSet.Tables[0].Rows[0]["Count"];

write-host $result;

Sada je potrebno kreirati datoteku s korisničkim parametrima i ekstenzijom .conf (ili dodati redove u postojeću takvu korisničku datoteku, ako je prethodno kreirana) i umetnuti sljedeće redove:
UserParameter=NAZIV_PARAMETRA_KOLICINA_OBAVLJENIH_UPITA,powershell -NoProfile -ExecutionPolicy Bypass -File PUN_PATHzabbixconfuserparams.dNAZIV_DATOTEKE_ZA_OBAVLJENE_UPITE.ps1
UserParameter=NAZIV_PARAMETRA_KOLICINA_CEKAJUCIH_UPITA,powershell -NoProfile -ExecutionPolicy Bypass -File PUN_PATHzabbixconfuserparams.dNAZIV_DATOTEKE_ZA_CEKAJUCE_UPITE.ps1
Nakon toga spasite datoteku .conf i ponovno pokrenite Zabbix agenta.
Nakon toga dodajemo u Zabbix nova dva elementa (u ovom slučaju nazivi i ključ se podudaraju):
NAZIV_PARAMETRA_KOLICINA_OBAVLJENIH_UPITA
NAZIV_PARAMETRA_KOLICINA_CEKAJUCIH_UPITA
Sada možemo kreirati grafike i okidače za stvorene korisničke elemente podataka.

Ako broj čekajućih zahtjeva naglo raste, sljedećim zahtjevom možete izvesti sve aktivne i čekajuće zahtjeve u trenutno vrijeme s detaljima odakle i pod kojim korisničkim imenom se izvršava zahtjev, tekstom i planom zahtjeva, kao i ostalim detaljima:
Kod

/*Активные, готовые к выполнению и ожидающие запросы, а также те, что явно блокируют другие сеансы*/
with tbl0 as (
	select ES.[session_id]
	      ,ER.[blocking_session_id]
		  ,ER.[request_id]
	      ,ER.[start_time]
	      ,ER.[status]
		  ,ES.[status] as [status_session]
	      ,ER.[command]
		  ,ER.[percent_complete]
		  ,DB_Name(coalesce(ER.[database_id], ES.[database_id])) as [DBName]
	      ,(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]
	      ,ER.[wait_type]
	      ,ES.[login_time]
		  ,ES.[host_name]
		  ,ES.[program_name]
	      ,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]
		  ,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
)
, tbl as (
	select [session_id]
	      ,[blocking_session_id]
		  ,[request_id]
	      ,[start_time]
	      ,[status]
		  ,[status_session]
	      ,[command]
		  ,[percent_complete]
		  ,[DBName]
		  ,OBJECT_name([objectid], [database_id]) as [object]
	      ,[TSQL]
		  ,[QueryPlan]
	      ,[wait_type]
	      ,[login_time]
		  ,[host_name]
		  ,[program_name]
	      ,[wait_time]
	      ,[last_wait_type]
	      ,[wait_resource]
	      ,[open_transaction_count]
	      ,[open_resultset_count]
	      ,[transaction_id]
	      ,[context_info]
	      ,[estimated_completion_time]
	      ,[cpu_time]
	      ,[total_elapsed_time]
	      ,[scheduler_id]
	      ,[task_address]
	      ,[reads]
	      ,[writes]
	      ,[logical_reads]
	      ,[text_size]
	      ,[language]
	      ,[date_format]
	      ,[date_first]
	      ,[quoted_identifier]
	      ,[arithabort]
	      ,[ansi_null_dflt_on]
	      ,[ansi_defaults]
	      ,[ansi_warnings]
	      ,[ansi_padding]
	      ,[ansi_nulls]
	      ,[concat_null_yields_null]
	      ,[transaction_isolation_level]
	      ,[lock_timeout]
	      ,[deadlock_priority]
	      ,[row_count]
	      ,[prev_error]
	      ,[nest_level]
	      ,[granted_query_memory]
	      ,[executing_managed_code]
	      ,[group_id]
	      ,[query_hash]
	      ,[query_plan_hash]
		  ,[most_recent_session_id]
	      ,[connect_time]
	      ,[net_transport]
	      ,[protocol_type]
	      ,[protocol_version]
	      ,[endpoint_id]
	      ,[encrypt_option]
	      ,[auth_scheme]
	      ,[node_affinity]
	      ,[num_reads]
	      ,[num_writes]
	      ,[last_read]
	      ,[last_write]
	      ,[net_packet_size]
	      ,[client_net_address]
	      ,[client_tcp_port]
	      ,[local_net_address]
	      ,[local_tcp_port]
	      ,[parent_connection_id]
	      ,[most_recent_sql_handle]
		  ,[host_process_id]
		  ,[client_version]
		  ,[client_interface_name]
		  ,[security_id]
		  ,[login_name]
		  ,[nt_domain]
		  ,[nt_user_name]
		  ,[memory_usage]
		  ,[total_scheduled_time]
		  ,[last_request_start_time]
		  ,[last_request_end_time]
		  ,[is_user_process]
		  ,[original_security_id]
		  ,[original_login_name]
		  ,[last_successful_logon]
		  ,[last_unsuccessful_logon]
		  ,[unsuccessful_logons]
		  ,[authenticating_database_id]
		  ,[sql_handle]
	      ,[statement_start_offset]
	      ,[statement_end_offset]
	      ,[plan_handle]
		  ,[dop]
	      ,[database_id]
	      ,[user_id]
	      ,[connection_id]
	from tbl0
	where [status] in ('suspended', 'running', 'runnable')
)
, tbl_group as (
	select [blocking_session_id]
	from tbl
	where [blocking_session_id]<>0
	group by [blocking_session_id]
)
, tbl_res_rec as (
	select [session_id]
	      ,[blocking_session_id]
		  ,[request_id]
	      ,[start_time]
	      ,[status]
		  ,[status_session]
	      ,[command]
		  ,[percent_complete]
		  ,[DBName]
		  ,[object]
	      ,[TSQL]
		  ,[QueryPlan]
	      ,[wait_type]
	      ,[login_time]
		  ,[host_name]
		  ,[program_name]
	      ,[wait_time]
	      ,[last_wait_type]
	      ,[wait_resource]
	      ,[open_transaction_count]
	      ,[open_resultset_count]
	      ,[transaction_id]
	      ,[context_info]
	      ,[estimated_completion_time]
	      ,[cpu_time]
	      ,[total_elapsed_time]
	      ,[scheduler_id]
	      ,[task_address]
	      ,[reads]
	      ,[writes]
	      ,[logical_reads]
	      ,[text_size]
	      ,[language]
	      ,[date_format]
	      ,[date_first]
	      ,[quoted_identifier]
	      ,[arithabort]
	      ,[ansi_null_dflt_on]
	      ,[ansi_defaults]
	      ,[ansi_warnings]
	      ,[ansi_padding]
	      ,[ansi_nulls]
	      ,[concat_null_yields_null]
	      ,[transaction_isolation_level]
	      ,[lock_timeout]
	      ,[deadlock_priority]
	      ,[row_count]
	      ,[prev_error]
	      ,[nest_level]
	      ,[granted_query_memory]
	      ,[executing_managed_code]
	      ,[group_id]
	      ,[query_hash]
	      ,[query_plan_hash]
		  ,[most_recent_session_id]
	      ,[connect_time]
	      ,[net_transport]
	      ,[protocol_type]
	      ,[protocol_version]
	      ,[endpoint_id]
	      ,[encrypt_option]
	      ,[auth_scheme]
	      ,[node_affinity]
	      ,[num_reads]
	      ,[num_writes]
	      ,[last_read]
	      ,[last_write]
	      ,[net_packet_size]
	      ,[client_net_address]
	      ,[client_tcp_port]
	      ,[local_net_address]
	      ,[local_tcp_port]
	      ,[parent_connection_id]
	      ,[most_recent_sql_handle]
		  ,[host_process_id]
		  ,[client_version]
		  ,[client_interface_name]
		  ,[security_id]
		  ,[login_name]
		  ,[nt_domain]
		  ,[nt_user_name]
		  ,[memory_usage]
		  ,[total_scheduled_time]
		  ,[last_request_start_time]
		  ,[last_request_end_time]
		  ,[is_user_process]
		  ,[original_security_id]
		  ,[original_login_name]
		  ,[last_successful_logon]
		  ,[last_unsuccessful_logon]
		  ,[unsuccessful_logons]
		  ,[authenticating_database_id]
		  ,[sql_handle]
	      ,[statement_start_offset]
	      ,[statement_end_offset]
	      ,[plan_handle]
		  ,[dop]
	      ,[database_id]
	      ,[user_id]
	      ,[connection_id]
		  , 0 as [is_blocking_other_session]
from tbl
union all
select tbl0.[session_id]
	      ,tbl0.[blocking_session_id]
		  ,tbl0.[request_id]
	      ,tbl0.[start_time]
	      ,tbl0.[status]
		  ,tbl0.[status_session]
	      ,tbl0.[command]
		  ,tbl0.[percent_complete]
		  ,tbl0.[DBName]
		  ,OBJECT_name(tbl0.[objectid], tbl0.[database_id]) as [object]
	      ,tbl0.[TSQL]
		  ,tbl0.[QueryPlan]
	      ,tbl0.[wait_type]
	      ,tbl0.[login_time]
		  ,tbl0.[host_name]
		  ,tbl0.[program_name]
	      ,tbl0.[wait_time]
	      ,tbl0.[last_wait_type]
	      ,tbl0.[wait_resource]
	      ,tbl0.[open_transaction_count]
	      ,tbl0.[open_resultset_count]
	      ,tbl0.[transaction_id]
	      ,tbl0.[context_info]
	      ,tbl0.[estimated_completion_time]
	      ,tbl0.[cpu_time]
	      ,tbl0.[total_elapsed_time]
	      ,tbl0.[scheduler_id]
	      ,tbl0.[task_address]
	      ,tbl0.[reads]
	      ,tbl0.[writes]
	      ,tbl0.[logical_reads]
	      ,tbl0.[text_size]
	      ,tbl0.[language]
	      ,tbl0.[date_format]
	      ,tbl0.[date_first]
	      ,tbl0.[quoted_identifier]
	      ,tbl0.[arithabort]
	      ,tbl0.[ansi_null_dflt_on]
	      ,tbl0.[ansi_defaults]
	      ,tbl0.[ansi_warnings]
	      ,tbl0.[ansi_padding]
	      ,tbl0.[ansi_nulls]
	      ,tbl0.[concat_null_yields_null]
	      ,tbl0.[transaction_isolation_level]
	      ,tbl0.[lock_timeout]
	      ,tbl0.[deadlock_priority]
	      ,tbl0.[row_count]
	      ,tbl0.[prev_error]
	      ,tbl0.[nest_level]
	      ,tbl0.[granted_query_memory]
	      ,tbl0.[executing_managed_code]
	      ,tbl0.[group_id]
	      ,tbl0.[query_hash]
	      ,tbl0.[query_plan_hash]
		  ,tbl0.[most_recent_session_id]
	      ,tbl0.[connect_time]
	      ,tbl0.[net_transport]
	      ,tbl0.[protocol_type]
	      ,tbl0.[protocol_version]
	      ,tbl0.[endpoint_id]
	      ,tbl0.[encrypt_option]
	      ,tbl0.[auth_scheme]
	      ,tbl0.[node_affinity]
	      ,tbl0.[num_reads]
	      ,tbl0.[num_writes]
	      ,tbl0.[last_read]
	      ,tbl0.[last_write]
	      ,tbl0.[net_packet_size]
	      ,tbl0.[client_net_address]
	      ,tbl0.[client_tcp_port]
	      ,tbl0.[local_net_address]
	      ,tbl0.[local_tcp_port]
	      ,tbl0.[parent_connection_id]
	      ,tbl0.[most_recent_sql_handle]
		  ,tbl0.[host_process_id]
		  ,tbl0.[client_version]
		  ,tbl0.[client_interface_name]
		  ,tbl0.[security_id]
		  ,tbl0.[login_name]
		  ,tbl0.[nt_domain]
		  ,tbl0.[nt_user_name]
		  ,tbl0.[memory_usage]
		  ,tbl0.[total_scheduled_time]
		  ,tbl0.[last_request_start_time]
		  ,tbl0.[last_request_end_time]
		  ,tbl0.[is_user_process]
		  ,tbl0.[original_security_id]
		  ,tbl0.[original_login_name]
		  ,tbl0.[last_successful_logon]
		  ,tbl0.[last_unsuccessful_logon]
		  ,tbl0.[unsuccessful_logons]
		  ,tbl0.[authenticating_database_id]
		  ,tbl0.[sql_handle]
	      ,tbl0.[statement_start_offset]
	      ,tbl0.[statement_end_offset]
	      ,tbl0.[plan_handle]
		  ,tbl0.[dop]
	      ,tbl0.[database_id]
	      ,tbl0.[user_id]
	      ,tbl0.[connection_id]
		  , 1 as [is_blocking_other_session]
	from tbl_group as tg
	inner join tbl0 on tg.blocking_session_id=tbl0.session_id
)
,tbl_res_rec_g as (
	select [plan_handle],
		   [sql_handle],
		   cast([start_time] as date) as [start_time]
	from tbl_res_rec
	group by [plan_handle],
			 [sql_handle],
			 cast([start_time] as date)
)
,tbl_rec_stat_g as (
	select qs.[plan_handle]
		  ,qs.[sql_handle]
		  --,cast(qs.[last_execution_time] as date)	as [last_execution_time]
		  ,min(qs.[creation_time])					as [creation_time]
		  ,max(qs.[execution_count])				as [execution_count]
		  ,max(qs.[total_worker_time])				as [total_worker_time]
		  ,min(qs.[last_worker_time])				as [min_last_worker_time]
		  ,max(qs.[last_worker_time])				as [max_last_worker_time]
		  ,min(qs.[min_worker_time])				as [min_worker_time]
		  ,max(qs.[max_worker_time])				as [max_worker_time]
		  ,max(qs.[total_physical_reads])			as [total_physical_reads]
		  ,min(qs.[last_physical_reads])			as [min_last_physical_reads]
		  ,max(qs.[last_physical_reads])			as [max_last_physical_reads]
		  ,min(qs.[min_physical_reads])				as [min_physical_reads]
		  ,max(qs.[max_physical_reads])				as [max_physical_reads]
		  ,max(qs.[total_logical_writes])			as [total_logical_writes]
		  ,min(qs.[last_logical_writes])			as [min_last_logical_writes]
		  ,max(qs.[last_logical_writes])			as [max_last_logical_writes]
		  ,min(qs.[min_logical_writes])				as [min_logical_writes]
		  ,max(qs.[max_logical_writes])				as [max_logical_writes]
		  ,max(qs.[total_logical_reads])			as [total_logical_reads]
		  ,min(qs.[last_logical_reads])				as [min_last_logical_reads]
		  ,max(qs.[last_logical_reads])				as [max_last_logical_reads]
		  ,min(qs.[min_logical_reads])				as [min_logical_reads]
		  ,max(qs.[max_logical_reads])				as [max_logical_reads]
		  ,max(qs.[total_clr_time])					as [total_clr_time]
		  ,min(qs.[last_clr_time])					as [min_last_clr_time]
		  ,max(qs.[last_clr_time])					as [max_last_clr_time]
		  ,min(qs.[min_clr_time])					as [min_clr_time]
		  ,max(qs.[max_clr_time])					as [max_clr_time]
		  ,max(qs.[total_elapsed_time])				as [total_elapsed_time]
		  ,min(qs.[last_elapsed_time])				as [min_last_elapsed_time]
		  ,max(qs.[last_elapsed_time])				as [max_last_elapsed_time]
		  ,min(qs.[min_elapsed_time])				as [min_elapsed_time]
		  ,max(qs.[max_elapsed_time])				as [max_elapsed_time]
		  ,max(qs.[total_rows])						as [total_rows]
		  ,min(qs.[last_rows])						as [min_last_rows]
		  ,max(qs.[last_rows])						as [max_last_rows]
		  ,min(qs.[min_rows])						as [min_rows]
		  ,max(qs.[max_rows])						as [max_rows]
		  ,max(qs.[total_dop])						as [total_dop]
		  ,min(qs.[last_dop])						as [min_last_dop]
		  ,max(qs.[last_dop])						as [max_last_dop]
		  ,min(qs.[min_dop])						as [min_dop]
		  ,max(qs.[max_dop])						as [max_dop]
		  ,max(qs.[total_grant_kb])					as [total_grant_kb]
		  ,min(qs.[last_grant_kb])					as [min_last_grant_kb]
		  ,max(qs.[last_grant_kb])					as [max_last_grant_kb]
		  ,min(qs.[min_grant_kb])					as [min_grant_kb]
		  ,max(qs.[max_grant_kb])					as [max_grant_kb]
		  ,max(qs.[total_used_grant_kb])			as [total_used_grant_kb]
		  ,min(qs.[last_used_grant_kb])				as [min_last_used_grant_kb]
		  ,max(qs.[last_used_grant_kb])				as [max_last_used_grant_kb]
		  ,min(qs.[min_used_grant_kb])				as [min_used_grant_kb]
		  ,max(qs.[max_used_grant_kb])				as [max_used_grant_kb]
		  ,max(qs.[total_ideal_grant_kb])			as [total_ideal_grant_kb]
		  ,min(qs.[last_ideal_grant_kb])			as [min_last_ideal_grant_kb]
		  ,max(qs.[last_ideal_grant_kb])			as [max_last_ideal_grant_kb]
		  ,min(qs.[min_ideal_grant_kb])				as [min_ideal_grant_kb]
		  ,max(qs.[max_ideal_grant_kb])				as [max_ideal_grant_kb]
		  ,max(qs.[total_reserved_threads])			as [total_reserved_threads]
		  ,min(qs.[last_reserved_threads])			as [min_last_reserved_threads]
		  ,max(qs.[last_reserved_threads])			as [max_last_reserved_threads]
		  ,min(qs.[min_reserved_threads])			as [min_reserved_threads]
		  ,max(qs.[max_reserved_threads])			as [max_reserved_threads]
		  ,max(qs.[total_used_threads])				as [total_used_threads]
		  ,min(qs.[last_used_threads])				as [min_last_used_threads]
		  ,max(qs.[last_used_threads])				as [max_last_used_threads]
		  ,min(qs.[min_used_threads])				as [min_used_threads]
		  ,max(qs.[max_used_threads])				as [max_used_threads]
	from tbl_res_rec_g as t
	inner join sys.dm_exec_query_stats as qs with(readuncommitted) on t.[plan_handle]=qs.[plan_handle] 
																  and t.[sql_handle]=qs.[sql_handle] 
																  and t.[start_time]=cast(qs.[last_execution_time] as date)
	group by qs.[plan_handle]
			,qs.[sql_handle]
			--,qs.[last_execution_time]
)
select t.[session_id] --Сессия
	      ,t.[blocking_session_id] --Сессия, которая явно блокирует сессию [session_id]
		  ,t.[request_id] --Идентификатор запроса. Уникален в контексте сеанса
	      ,t.[start_time] --Метка времени поступления запроса
		  ,DateDiff(second, t.[start_time], GetDate()) as [date_diffSec] --Сколько в сек прошло времени от момента поступления запроса
	      ,t.[status] --Состояние запроса
		  ,t.[status_session] --Состояние сессии
	      ,t.[command] --Тип выполняемой в данный момент команды
		  , COALESCE(
						CAST(NULLIF(t.[total_elapsed_time] / 1000, 0) as BIGINT)
					   ,CASE WHEN (t.[status_session] <> 'running' and isnull(t.[status], '')  <> 'running') 
								THEN  DATEDIFF(ss,0,getdate() - nullif(t.[last_request_end_time], '1900-01-01T00:00:00.000'))
						END
					) as [total_time, sec] --Время всей работы запроса в сек
		  , CAST(NULLIF((CAST(t.[total_elapsed_time] as BIGINT) - CAST(t.[wait_time] AS BIGINT)) / 1000, 0 ) as bigint) as [work_time, sec] --Время работы запроса в сек без учета времени ожиданий
		  , CASE WHEN (t.[status_session] <> 'running' AND ISNULL(t.[status],'') <> 'running') 
		  			THEN  DATEDIFF(ss,0,getdate() - nullif(t.[last_request_end_time], '1900-01-01T00:00:00.000'))
			END as [sleep_time, sec] --Время сна в сек
		  , NULLIF( CAST((t.[logical_reads] + t.[writes]) * 8 / 1024 as numeric(38,2)), 0) as [IO, MB] --операций чтения и записи в МБ
		  , CASE  t.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] --уровень изоляции транзакции (расшифровка)
		  ,t.[percent_complete] --Процент завершения работы для следующих команд
		  ,t.[DBName] --БД
		  ,t.[object] --Объект
		  , SUBSTRING(
						t.[TSQL]
					  , t.[statement_start_offset]/2+1
					  ,	(
							CASE WHEN ((t.[statement_start_offset]<0) OR (t.[statement_end_offset]<0))
									THEN DATALENGTH (t.[TSQL])
								 ELSE t.[statement_end_offset]
							END
							- t.[statement_start_offset]
						)/2 +1
					 ) as [CURRENT_REQUEST] --Текущий выполняемый запрос в пакете
	      ,t.[TSQL] --Запрос всего пакета
		  ,t.[QueryPlan] --План всего пакета
	      ,t.[wait_type] --Если запрос в настоящий момент блокирован, в столбце содержится тип ожидания (sys.dm_os_wait_stats)
	      ,t.[login_time] --Время подключения сеанса
		  ,t.[host_name] --Имя клиентской рабочей станции, указанное в сеансе. Для внутреннего сеанса это значение равно NULL
		  ,t.[program_name] --Имя клиентской программы, которая инициировала сеанс. Для внутреннего сеанса это значение равно NULL
		  ,cast(t.[wait_time]/1000 as decimal(18,3)) as [wait_timeSec] --Если запрос в настоящий момент блокирован, в столбце содержится продолжительность текущего ожидания (в секундах)
	      ,t.[wait_time] --Если запрос в настоящий момент блокирован, в столбце содержится продолжительность текущего ожидания (в миллисекундах)
	      ,t.[last_wait_type] --Если запрос был блокирован ранее, в столбце содержится тип последнего ожидания
	      ,t.[wait_resource] --Если запрос в настоящий момент блокирован, в столбце указан ресурс, освобождения которого ожидает запрос
	      ,t.[open_transaction_count] --Число транзакций, открытых для данного запроса
	      ,t.[open_resultset_count] --Число результирующих наборов, открытых для данного запроса
	      ,t.[transaction_id] --Идентификатор транзакции, в которой выполняется запрос
	      ,t.[context_info] --Значение CONTEXT_INFO сеанса
		  ,cast(t.[estimated_completion_time]/1000 as decimal(18,3)) as [estimated_completion_timeSec] --Только для внутреннего использования. Не допускает значение NULL
	      ,t.[estimated_completion_time] --Только для внутреннего использования. Не допускает значение NULL
		  ,cast(t.[cpu_time]/1000 as decimal(18,3)) as [cpu_timeSec] --Время ЦП (в секундах), затраченное на выполнение запроса
	      ,t.[cpu_time] --Время ЦП (в миллисекундах), затраченное на выполнение запроса
		  ,cast(t.[total_elapsed_time]/1000 as decimal(18,3)) as [total_elapsed_timeSec] --Общее время, истекшее с момента поступления запроса (в секундах)
	      ,t.[total_elapsed_time] --Общее время, истекшее с момента поступления запроса (в миллисекундах)
	      ,t.[scheduler_id] --Идентификатор планировщика, который планирует данный запрос
	      ,t.[task_address] --Адрес блока памяти, выделенного для задачи, связанной с этим запросом
	      ,t.[reads] --Число операций чтения, выполненных данным запросом
	      ,t.[writes] --Число операций записи, выполненных данным запросом
	      ,t.[logical_reads] --Число логических операций чтения, выполненных данным запросом
	      ,t.[text_size] --Установка параметра TEXTSIZE для данного запроса
	      ,t.[language] --Установка языка для данного запроса
	      ,t.[date_format] --Установка параметра DATEFORMAT для данного запроса
	      ,t.[date_first] --Установка параметра DATEFIRST для данного запроса
	      ,t.[quoted_identifier] --1 = Параметр QUOTED_IDENTIFIER для запроса включен (ON). В противном случае — 0
	      ,t.[arithabort] --1 = Параметр ARITHABORT для запроса включен (ON). В противном случае — 0
	      ,t.[ansi_null_dflt_on] --1 = Параметр ANSI_NULL_DFLT_ON для запроса включен (ON). В противном случае — 0
	      ,t.[ansi_defaults] --1 = Параметр ANSI_DEFAULTS для запроса включен (ON). В противном случае — 0
	      ,t.[ansi_warnings] --1 = Параметр ANSI_WARNINGS для запроса включен (ON). В противном случае — 0
	      ,t.[ansi_padding] --1 = Параметр ANSI_PADDING для запроса включен (ON)
	      ,t.[ansi_nulls] --1 = Параметр ANSI_NULLS для запроса включен (ON). В противном случае — 0
	      ,t.[concat_null_yields_null] --1 = Параметр CONCAT_NULL_YIELDS_NULL для запроса включен (ON). В противном случае — 0
	      ,t.[transaction_isolation_level] --Уровень изоляции, с которым создана транзакция для данного запроса
		  ,cast(t.[lock_timeout]/1000 as decimal(18,3)) as [lock_timeoutSec] --Время ожидания блокировки для данного запроса (в секундах)
		  ,t.[lock_timeout] --Время ожидания блокировки для данного запроса (в миллисекундах)
	      ,t.[deadlock_priority] --Значение параметра DEADLOCK_PRIORITY для данного запроса
	      ,t.[row_count] --Число строк, возвращенных клиенту по данному запросу
	      ,t.[prev_error] --Последняя ошибка, происшедшая при выполнении запроса
	      ,t.[nest_level] --Текущий уровень вложенности кода, выполняемого для данного запроса
	      ,t.[granted_query_memory] --Число страниц, выделенных для выполнения поступившего запроса (1 страница-это примерно 8 КБ)
	      ,t.[executing_managed_code] --Указывает, выполняет ли данный запрос в настоящее время код объекта среды CLR (например, процедуры, типа или триггера).
									  --Этот флаг установлен в течение всего времени, когда объект среды CLR находится в стеке, даже когда из среды вызывается код Transact-SQL
	      
		  ,t.[group_id]	--Идентификатор группы рабочей нагрузки, которой принадлежит этот запрос
	      ,t.[query_hash] --Двоичное хэш-значение рассчитывается для запроса и используется для идентификации запросов с аналогичной логикой.
						  --Можно использовать хэш запроса для определения использования статистических ресурсов для запросов, которые отличаются только своими литеральными значениями
	      
		  ,t.[query_plan_hash] --Двоичное хэш-значение рассчитывается для плана выполнения запроса и используется для идентификации аналогичных планов выполнения запросов.
							   --Можно использовать хэш плана запроса для нахождения совокупной стоимости запросов со схожими планами выполнения
		  
		  ,t.[most_recent_session_id] --Представляет собой идентификатор сеанса самого последнего запроса, связанного с данным соединением
	      ,t.[connect_time] --Отметка времени установления соединения
	      ,t.[net_transport] --Содержит описание физического транспортного протокола, используемого данным соединением
	      ,t.[protocol_type] --Указывает тип протокола передачи полезных данных
	      ,t.[protocol_version] --Версия протокола доступа к данным, связанного с данным соединением
	      ,t.[endpoint_id] --Идентификатор, описывающий тип соединения. Этот идентификатор endpoint_id может использоваться для запросов к представлению sys.endpoints
	      ,t.[encrypt_option] --Логическое значение, указывающее, разрешено ли шифрование для данного соединения
	      ,t.[auth_scheme] --Указывает схему проверки подлинности (SQL Server или Windows), используемую с данным соединением
	      ,t.[node_affinity] --Идентифицирует узел памяти, которому соответствует данное соединение
	      ,t.[num_reads] --Число пакетов, принятых посредством данного соединения
	      ,t.[num_writes] --Число пакетов, переданных посредством данного соединения
	      ,t.[last_read] --Отметка времени о последнем полученном пакете данных
	      ,t.[last_write] --Отметка времени о последнем отправленном пакете данных
	      ,t.[net_packet_size] --Размер сетевого пакета, используемый для передачи данных
	      ,t.[client_net_address] --Сетевой адрес удаленного клиента
	      ,t.[client_tcp_port] --Номер порта на клиентском компьютере, который используется при осуществлении соединения
	      ,t.[local_net_address] --IP-адрес сервера, с которым установлено данное соединение. Доступен только для соединений, которые в качестве транспорта данных используют протокол TCP
	      ,t.[local_tcp_port] --TCP-порт сервера, если соединение использует протокол TCP
	      ,t.[parent_connection_id] --Идентифицирует первичное соединение, используемое в сеансе MARS
	      ,t.[most_recent_sql_handle] --Дескриптор последнего запроса SQL, выполненного с помощью данного соединения. Постоянно проводится синхронизация между столбцом most_recent_sql_handle и столбцом most_recent_session_id
		  ,t.[host_process_id] --Идентификатор процесса клиентской программы, которая инициировала сеанс. Для внутреннего сеанса это значение равно NULL
		  ,t.[client_version] --Версия TDS-протокола интерфейса, который используется клиентом для подключения к серверу. Для внутреннего сеанса это значение равно NULL
		  ,t.[client_interface_name] --Имя библиотеки или драйвер, используемый клиентом для обмена данными с сервером. Для внутреннего сеанса это значение равно NULL
		  ,t.[security_id] --Идентификатор безопасности Microsoft Windows, связанный с именем входа
		  ,t.[login_name] --SQL Server Имя входа, под которой выполняется текущий сеанс.
						  --Чтобы узнать первоначальное имя входа, с помощью которого был создан сеанс, см. параметр original_login_name.
						  --Может быть SQL Server проверка подлинности имени входа или имени пользователя домена, прошедшего проверку подлинности Windows
		  
		  ,t.[nt_domain] --Домен Windows для клиента, если во время сеанса применяется проверка подлинности Windows или доверительное соединение.
						 --Для внутренних сеансов и пользователей, не принадлежащих к домену, это значение равно NULL
		  
		  ,t.[nt_user_name] --Имя пользователя Windows для клиента, если во время сеанса используется проверка подлинности Windows или доверительное соединение.
							--Для внутренних сеансов и пользователей, не принадлежащих к домену, это значение равно NULL
		  
		  ,t.[memory_usage] --Количество 8-килобайтовых страниц памяти, используемых данным сеансом
		  ,t.[total_scheduled_time] --Общее время, назначенное данному сеансу (включая его вложенные запросы) для исполнения, в миллисекундах
		  ,t.[last_request_start_time] --Время, когда начался последний запрос данного сеанса. Это может быть запрос, выполняющийся в данный момент
		  ,t.[last_request_end_time] --Время завершения последнего запроса в рамках данного сеанса
		  ,t.[is_user_process] --0, если сеанс является системным. В противном случае значение равно 1
		  ,t.[original_security_id] --Microsoft Идентификатор безопасности Windows, связанный с параметром original_login_name
		  ,t.[original_login_name] --SQL Server Имя входа, которую использует клиент создал данный сеанс.
								   --Это может быть имя входа SQL Server, прошедшее проверку подлинности, имя пользователя домена Windows, 
								   --прошедшее проверку подлинности, или пользователь автономной базы данных.
								   --Обратите внимание, что после первоначального соединения для сеанса может быть выполнено много неявных или явных переключений контекста.
								   --Например если EXECUTE AS используется
		  
		  ,t.[last_successful_logon] --Время последнего успешного входа в систему для имени original_login_name до запуска текущего сеанса
		  ,t.[last_unsuccessful_logon] --Время последнего неуспешного входа в систему для имени original_login_name до запуска текущего сеанса
		  ,t.[unsuccessful_logons] --Число неуспешных попыток входа в систему для имени original_login_name между временем last_successful_logon и временем login_time
		  ,t.[authenticating_database_id] --Идентификатор базы данных, выполняющей проверку подлинности участника.
										  --Для имен входа это значение будет равно 0.
										  --Для пользователей автономной базы данных это значение будет содержать идентификатор автономной базы данных
		  
		  ,t.[sql_handle] --Хэш-карта текста SQL-запроса
	      ,t.[statement_start_offset] --Количество символов в выполняемом в настоящий момент пакете или хранимой процедуре, в которой запущена текущая инструкция.
									  --Может применяться вместе с функциями динамического управления sql_handle, statement_end_offset и sys.dm_exec_sql_text
									  --для извлечения исполняемой в настоящий момент инструкции по запросу
	      
		  ,t.[statement_end_offset] --Количество символов в выполняемом в настоящий момент пакете или хранимой процедуре, в которой завершилась текущая инструкция.
									--Может применяться вместе с функциями динамического управления sql_handle, statement_end_offset и sys.dm_exec_sql_text
									--для извлечения исполняемой в настоящий момент инструкции по запросу
	      
		  ,t.[plan_handle] --Хэш-карта плана выполнения SQL
	      ,t.[database_id] --Идентификатор базы данных, к которой выполняется запрос
	      ,t.[user_id] --Идентификатор пользователя, отправившего данный запрос
	      ,t.[connection_id] --Идентификатор соединения, по которому поступил запрос
		  ,t.[is_blocking_other_session] --1-сессия явно блокирует другие сессии, 0-сессия явно не блокирует другие сессии
		  ,coalesce(t.[dop], mg.[dop]) as [dop] --Степень параллелизма запроса
		  ,mg.[request_time] --Дата и время обращения запроса за предоставлением памяти
		  ,mg.[grant_time] --Дата и время, когда запросу была предоставлена память. Возвращает значение NULL, если память еще не была предоставлена
		  ,mg.[requested_memory_kb] --Общий объем запрошенной памяти в килобайтах
		  ,mg.[granted_memory_kb] --Общий объем фактически предоставленной памяти в килобайтах.
								  --Может быть значение NULL, если память еще не была предоставлена.
								  --Обычно это значение должно быть одинаковым с requested_memory_kb.
								  --Для создания индекса сервер может разрешить дополнительное предоставление по требованию памяти,
								  --объем которой выходит за рамки изначально предоставленной памяти
		  
		  ,mg.[required_memory_kb] --Минимальный объем памяти в килобайтах (КБ), необходимый для выполнения данного запроса.
								   --Значение requested_memory_kb равно этому объему или больше его
		  
		  ,mg.[used_memory_kb] --Используемый в данный момент объем физической памяти (в килобайтах)
		  ,mg.[max_used_memory_kb] --Максимальный объем используемой до данного момента физической памяти в килобайтах
		  ,mg.[query_cost] --Ожидаемая стоимость запроса
		  ,mg.[timeout_sec] --Время ожидания данного запроса в секундах до отказа от обращения за предоставлением памяти
		  ,mg.[resource_semaphore_id] --Неуникальный идентификатор семафора ресурса, которого ожидает данный запрос
		  ,mg.[queue_id] --Идентификатор ожидающей очереди, в которой данный запрос ожидает предоставления памяти.
						 --Значение NULL, если память уже предоставлена
		  
		  ,mg.[wait_order] --Последовательный порядок ожидающих запросов в указанной очереди queue_id.
						   --Это значение может изменяться для заданного запроса, если другие запросы отказываются от предоставления памяти или получают ее.
						   --Значение NULL, если память уже предоставлена
		  
		  ,mg.[is_next_candidate] --Является следующим кандидатом на предоставление памяти (1 = да, 0 = нет, NULL = память уже предоставлена)
		  ,mg.[wait_time_ms] --Время ожидания в миллисекундах. Значение NULL, если память уже предоставлена
		  ,mg.[pool_id] --Идентификатор пула ресурсов, к которому принадлежит данная группа рабочей нагрузки
		  ,mg.[is_small] --Значение 1 означает, что для данной операции предоставления памяти используется малый семафор ресурса.
						 --Значение 0 означает использование обычного семафора
		  
		  ,mg.[ideal_memory_kb] --Объем, в килобайтах (КБ), предоставленной памяти, необходимый для размещения всех данных в физической памяти.
								--Основывается на оценке количества элементов
		  
		  ,mg.[reserved_worker_count] --Число рабочих процессов, зарезервированной с помощью параллельных запросов, а также число основных рабочих процессов, используемых всеми запросами
		  ,mg.[used_worker_count] --Число рабочих процессов, используемых параллельных запросов
		  ,mg.[max_used_worker_count] --???
		  ,mg.[reserved_node_bitmap] --???
		  ,pl.[bucketid] --Идентификатор сегмента хэша, в который кэшируется запись.
						 --Значение указывает диапазон от 0 до значения размера хэш-таблицы для типа кэша.
						 --Для кэшей SQL Plans и Object Plans размер хэш-таблицы может достигать 10007 на 32-разрядных версиях систем и 40009 — на 64-разрядных.
						 --Для кэша Bound Trees размер хэш-таблицы может достигать 1009 на 32-разрядных версиях систем и 4001 на 64-разрядных.
						 --Для кэша расширенных хранимых процедур размер хэш-таблицы может достигать 127 на 32-разрядных и 64-разрядных версиях систем
		  
		  ,pl.[refcounts] --Число объектов кэша, ссылающихся на данный объект кэша.
						  --Значение refcounts для записи должно быть не меньше 1, чтобы размещаться в кэше
		  
		  ,pl.[usecounts] --Количество повторений поиска объекта кэша.
						  --Остается без увеличения, если параметризованные запросы обнаруживают план в кэше.
						  --Может быть увеличен несколько раз при использовании инструкции showplan
		  
		  ,pl.[size_in_bytes] --Число байтов, занимаемых объектом кэша
		  ,pl.[memory_object_address] --Адрес памяти кэшированной записи.
									  --Это значение можно использовать с представлением sys.dm_os_memory_objects,
									  --чтобы проанализировать распределение памяти кэшированного плана, 
									  --и с представлением sys.dm_os_memory_cache_entries для определения затрат на кэширование записи
		  
		  ,pl.[cacheobjtype] --Тип объекта в кэше. Значение может быть одним из следующих
		  ,pl.[objtype] --Тип объекта. Значение может быть одним из следующих
		  ,pl.[parent_plan_handle] --Родительский план
		  
		  --данные из sys.dm_exec_query_stats брались за сутки, в которых была пара (запрос, план)
		  ,qs.[creation_time] --Время компиляции плана
		  ,qs.[execution_count] --Количество выполнений плана с момента последней компиляции
		  ,qs.[total_worker_time] --Общее время ЦП, затраченное на выполнение плана с момента компиляции, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[min_last_worker_time] --Минимальное время ЦП, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[max_last_worker_time] --Максимальное время ЦП, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[min_worker_time] --Минимальное время ЦП, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[max_worker_time] --Максимальное время ЦП, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[total_physical_reads] --Общее количество операций физического считывания при выполнении плана с момента его компиляции.
									 --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[min_last_physical_reads] --Минимальное количество операций физического считывания за время последнего выполнения плана.
										--Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[max_last_physical_reads] --Максимальное количество операций физического считывания за время последнего выполнения плана.
										--Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[min_physical_reads] --Минимальное количество операций физического считывания за одно выполнение плана.
								   --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[max_physical_reads] --Максимальное количество операций физического считывания за одно выполнение плана.
								   --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[total_logical_writes] --Общее количество операций логической записи при выполнении плана с момента его компиляции.
									 --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[min_last_logical_writes] --Минимальное количество страниц в буферном пуле, загрязненных во время последнего выполнения плана.
										--Если страница уже является «грязной» (т. е. измененной), операции записи не учитываются.
										--Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[max_last_logical_writes] --Максимальное количество страниц в буферном пуле, загрязненных во время последнего выполнения плана.
										--Если страница уже является «грязной» (т. е. измененной), операции записи не учитываются.
										--Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[min_logical_writes] --Минимальное количество операций логической записи за одно выполнение плана.
								   --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[max_logical_writes] --Максимальное количество операций логической записи за одно выполнение плана.
								   --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[total_logical_reads] --Общее количество операций логического считывания при выполнении плана с момента его компиляции.
									--Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[min_last_logical_reads] --Минимальное количество операций логического считывания за время последнего выполнения плана.
									   --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[max_last_logical_reads] --Максимальное количество операций логического считывания за время последнего выполнения плана.
									   --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[min_logical_reads]	   --Минимальное количество операций логического считывания за одно выполнение плана.
									   --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[max_logical_reads]	--Максимальное количество операций логического считывания за одно выполнение плана.
									--Значение всегда равно 0 при запросе оптимизированной для памяти таблицы
		  
		  ,qs.[total_clr_time]	--Время, в микросекундах (но с точностью до миллисекунды),
								--внутри Microsoft .NET Framework общеязыковая среда выполнения (CLR) объекты при выполнении плана с момента его компиляции.
								--Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями
		  
		  ,qs.[min_last_clr_time] --Минимальное время, в микросекундах (но с точностью до миллисекунды),
								  --затраченное внутри .NET Framework объекты среды CLR во время последнего выполнения плана.
								  --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями
		  
		  ,qs.[max_last_clr_time] --Максимальное время, в микросекундах (но с точностью до миллисекунды),
								  --затраченное внутри .NET Framework объекты среды CLR во время последнего выполнения плана.
								  --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями
		  
		  ,qs.[min_clr_time] --Минимальное время, когда-либо затраченное на выполнение плана внутри объектов .NET Framework среды CLR,
							 --в микросекундах (но с точностью до миллисекунды).
							 --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями
		  
		  ,qs.[max_clr_time] --Максимальное время, когда-либо затраченное на выполнение плана внутри среды CLR .NET Framework,
							 --в микросекундах (но с точностью до миллисекунды).
							 --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями
		  
		  --,qs.[total_elapsed_time] --Общее время, затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[min_last_elapsed_time] --Минимальное время, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[max_last_elapsed_time] --Максимальное время, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[min_elapsed_time] --Минимальное время, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[max_elapsed_time] --Максимальное время, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды)
		  ,qs.[total_rows] --Общее число строк, возвращаемых запросом. Не может иметь значение null.
						   --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу
		  
		  ,qs.[min_last_rows] --Минимальное число строк, возвращенных последним выполнением запроса. Не может иметь значение null.
							  --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу
		  
		  ,qs.[max_last_rows] --Максимальное число строк, возвращенных последним выполнением запроса. Не может иметь значение null.
							  --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу
		  
		  ,qs.[min_rows] --Минимальное количество строк, когда-либо возвращенных по запросу во время выполнения один
						 --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу
		  
		  ,qs.[max_rows] --Максимальное число строк, когда-либо возвращенных по запросу во время выполнения один
						 --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу
		  
		  ,qs.[total_dop] --Общую сумму по степени параллелизма плана используется с момента его компиляции.
						  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_last_dop] --Минимальная степень параллелизма, если время последнего выполнения плана.
							 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_last_dop] --Максимальная степень параллелизма, если время последнего выполнения плана.
							 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_dop] --Минимальная степень параллелизма этот план когда-либо используется во время одного выполнения.
						--Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_dop] --Максимальная степень параллелизма этот план когда-либо используется во время одного выполнения.
						--Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[total_grant_kb] --Общий объем зарезервированной памяти в КБ предоставить этот план, полученных с момента его компиляции.
							   --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_last_grant_kb] --Минимальный объем зарезервированной памяти предоставляет в КБ, когда время последнего выполнения плана.
								  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_last_grant_kb] --Максимальный объем зарезервированной памяти предоставляет в КБ, когда время последнего выполнения плана.
								  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_grant_kb] --Минимальный объем зарезервированной памяти в КБ предоставить никогда не получено в ходе одного выполнения плана.
							 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_grant_kb] --Максимальный объем зарезервированной памяти в КБ предоставить никогда не получено в ходе одного выполнения плана.
							 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[total_used_grant_kb] --Общий объем зарезервированной памяти в КБ предоставить этот план, используемый с момента его компиляции.
									--Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_last_used_grant_kb] --Минимальная сумма предоставления используемой памяти в КБ, если время последнего выполнения плана.
									   --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_last_used_grant_kb] --Максимальная сумма предоставления используемой памяти в КБ, если время последнего выполнения плана.
									   --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_used_grant_kb] --Минимальный объем используемой памяти в КБ предоставить никогда не используется при выполнении одного плана.
								  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_used_grant_kb] --Максимальный объем используемой памяти в КБ предоставить никогда не используется при выполнении одного плана.
								  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[total_ideal_grant_kb] --Общий объем идеальный память в КБ, оценка плана с момента его компиляции.
									 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_last_ideal_grant_kb] --Минимальный объем памяти, идеальным предоставляет в КБ, когда время последнего выполнения плана.
										--Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_last_ideal_grant_kb] --Максимальный объем памяти, идеальным предоставляет в КБ, когда время последнего выполнения плана.
										--Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_ideal_grant_kb] --Минимальный объем памяти идеальный предоставления в этот план когда-либо оценка во время выполнения один КБ.
								   --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_ideal_grant_kb] --Максимальный объем памяти идеальный предоставления в этот план когда-либо оценка во время выполнения один КБ.
								   --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[total_reserved_threads] --Общая сумма по зарезервированным параллельного потоков этот план когда-либо использовавшегося с момента его компиляции.
									   --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_last_reserved_threads] --Минимальное число зарезервированных параллельных потоков, когда время последнего выполнения плана.
										  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_last_reserved_threads] --Максимальное число зарезервированных параллельных потоков, когда время последнего выполнения плана.
										  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_reserved_threads] --Минимальное число зарезервированных параллельного потоков, когда-либо использовать при выполнении одного плана.
									 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_reserved_threads] --Максимальное число зарезервированных параллельного потоков никогда не используется при выполнении одного плана.
									 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[total_used_threads] --Общая сумма используется параллельных потоков этот план когда-либо использовавшегося с момента его компиляции.
								   --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_last_used_threads] --Минимальное число используемых параллельных потоков, когда время последнего выполнения плана.
									  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_last_used_threads] --Максимальное число используемых параллельных потоков, когда время последнего выполнения плана.
									  --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[min_used_threads] --Минимальное число используемых параллельных потоков, при выполнении одного плана использовали.
								 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
		  
		  ,qs.[max_used_threads] --Максимальное число используемых параллельных потоков, при выполнении одного плана использовали.
								 --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти
from tbl_res_rec as t
left outer join sys.dm_exec_query_memory_grants as mg on t.[plan_handle]=mg.[plan_handle] and t.[sql_handle]=mg.[sql_handle]
left outer join sys.dm_exec_cached_plans as pl on t.[plan_handle]=pl.[plan_handle]
left outer join tbl_rec_stat_g as qs on t.[plan_handle]=qs.[plan_handle] and t.[sql_handle]=qs.[sql_handle] --and qs.[last_execution_time]=cast(t.[start_time] as date);

Također napominjem da se iz prikupljenih statistika mogu dobiti najteži zahtjevi:
Kod

/*
creation_time - Время, когда запрос был скомпилирован. Поскольку при старте сервера кэш пустой, данное время всегда больше либо равно моменту запуска сервиса. Если время, указанное в этом столбце позже, чем предполагаемое (первое использование процедуры), это говорит о том, что запрос по тем или иным причинам был рекомпилирован.
last_execution_time - Момент фактического последнего выполнения запроса.
execution_count - Сколько раз запрос был выполнен с момента компиляции
Количество выполнений позволяет найти ошибки в алгоритмах - часто в наиболее выполняемых запросах оказываются те, которые находятся внутри каких-либо циклов однако могут быть выполнены перед самим циклом один раз. Например, получение каких-либо параметров из базы данных, не меняющихся внутри цикла.
CPU - Суммарное время использования процессора в миллисекундах. Если запрос обрабатывается параллельно, то это время может превысить общее время выполнения запроса, поскольку суммируется время использования запроса каждым ядром. Во время использования процессора включается только фактическая нагрузка на ядра, в нее не входят ожидания каких-либо ресурсов.
Очевидно, что данный показатель позволяет выявлять запросы, наиболее сильно загружающие процессор.
AvgCPUTime - Средняя загрузка процессора на один запрос. 
TotDuration - Общее время выполнения запроса, в миллисекундах.
Данный параметр может быть использован для поиска тех запросов, которые, независимо от причины выполняются "наиболее долго". Если общее время выполнения запроса существенно ниже времени CPU (с поправкой на параллелизм) - это говорит о том, что при выполнения запроса были ожидания каких-либо ресурсов. В большинстве случаев это связано с дисковой активностью или блокировками, но также это может быть сетевой интерфейс или другой ресурс. 
Полный список типов ожиданий можно посмотреть в описании представления sys.dm_os_wait_stats.
AvgDur - Среднее время выполнения запроса в миллисекундах.
Reads - Общее количество чтений.
Это пожалуй лучший агрегатный показатель, позволяющий выявить наиболее нагружающие сервер запросы.
Логическое чтение - это разовое обращение к странице данных, физические чтения не учитываются.
В рамках выполнения одного запроса, могут происходить неоднократные обращения к одной и той же странице.
Чем больше обращений к страницам, тем больше требуется дисковых чтений, памяти и, если речь идет о повторных обращениях, большее время требуется удерживать страницы в памяти.
Writes - Общее количество изменений страниц данных.
Характеризует то, как запрос "нагружает" дисковую систему операциями записи.
Следует помнить, что этот показатель может быть больше 0 не только у тех запросов, которые явно меняют данные, но также и у тех, которые сохраняют промежуточные данные в tempdb.
AggIO - Общее количество логических операций ввода-вывода (суммарно)
Как правило, количество логических чтений на порядки превышает количество операций записи, поэтому этот показатель сам по себе для анализа применим в редких случаях.
AvgIO - Среднее количество логических дисковых операций на одно выполнение запроса.
Значение данного показателя можно анализировать из следующих соображений:
Одна страница данных - это 8192 байта. Можно получить среднее количество байт данных, "обрабатываемых" данным запросом. Если этот объем превышает реальное количество данных, которые обрабатывает запрос (суммарный объем данных в используемых в запросе таблицах), это говорит о том, что был выбран заведомо плохой план выполнения и требуется заняться оптимизацией данного запроса.
Я встречал случай, когда один запрос делал количество обращений, эквивалентных объему в 5Тб, при этом общий объем данных в это БД был 300Гб, а объем данных в таблицах, задействованных в запросе не превышал 10Гб.
В общем можно описать одну причину такого поведения сервера - вместо использования индекса сервер предпочитает сканировать таблицу или наоборот.
Если объем логических чтений в разы превосходит общие объем данных, то это вызвано повторным обращениям к одним и тем же страницам данных. Помимо того, что в одном запросе таблица может быть использована несколько раз, к одним и тем же страницам сервер обращается например в случаях, когда используется индекс и по результатам поиска по нему, найденные некоторые строки данных лежат на одной и той же странице. Конечно, в таком случае предпочтительным могло бы быть сканирование таблицы - в этом случае сервер обращался бы к каждой странице данных только один раз. Однако этому часто мешают... попытки оптимизации запросов, когда разработчик явно указывает, какой индекс или тип соединения должен быть использован.
Обратный случай - вместо использования индекса было выбрано сканирование таблицы. Как правило, это связано с тем, что статистика устарела и требуется её обновление. Однако и в этом случае причиной неудачно выбранного плана вполне могут оказаться подсказки оптимизатору запросов.
query_text - Текст самого запроса
database_name - Имя базы данных, в находится объект, содержащий запрос. NULL для системных процедур
object_name - Имя объекта (процедуры или функции), содержащего запрос.
*/
with s as (
	select  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
	from sys.dm_exec_query_stats as qs with(readuncommitted)
	where convert(money, (qs.total_elapsed_time))/(execution_count*1000)>=100 --выполнялся запрос не менее 100 мс
)
select
	s.creation_time,
	s.last_execution_time,
	s.execution_count,
	s.CPU,
	s.[AvgCPUTime],
	s.TotDuration,
	s.[AvgDur],
	s.[Reads],
	s.[Writes],
	s.[AggIO],
	s.[AvgIO],
	--st.text as query_text,
	case 
		when sql_handle IS NULL then ' '
		else(substring(st.text,(s.statement_start_offset+2)/2,(
			case
				when s.statement_end_offset =-1 then len(convert(nvarchar(MAX),st.text))*2      
				else s.statement_end_offset    
			end - s.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],
	s.[sql_handle],
	s.plan_handle
from s
cross apply sys.dm_exec_sql_text(s.[sql_handle]) as st
cross apply sys.dm_exec_query_plan(s.[plan_handle]) as sp

Također se može napisati i za MySQL. Da biste to učinili, potrebno je instalirati mysql-connector-net i zatim napisati otprilike ovakav kod:
Kod za čekajuće upite

#Задаем переменные для подключение к MySQL и само подключение
[string]$sMySQLUserName = 'UserName'
[string]$sMySQLPW = 'UserPassword'
[string]$sMySQLDB = 'db'
[string]$sMySQLHost = 'IP-address'
[void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data");
[string]$sConnectionString = "server="+$sMySQLHost+";port=3306;uid=" + $sMySQLUserName + ";pwd="+"'" + $sMySQLPW +"'"+ ";database="+$sMySQLDB;

#Open a Database connection
$oConnection = New-Object MySql.Data.MySqlClient.MySqlConnection($sConnectionString)
$Error.Clear()
try
{
    $oConnection.Open()
}
catch
{
    write-warning ("Could not open a connection to Database $sMySQLDB on Host $sMySQLHost. Error: "+$Error[0].ToString())
}

#The first query
# Get an instance of all objects need for a SELECT query. The Command object
$oMYSQLCommand = New-Object MySql.Data.MySqlClient.MySqlCommand;
# DataAdapter Object
$oMYSQLDataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter;
# And the DataSet Object
$oMYSQLDataSet = New-Object System.Data.DataSet;
# Assign the established MySQL connection
$oMYSQLCommand.Connection=$oConnection;
# Define a SELECT query
$oMYSQLCommand.CommandText='query';

$oMYSQLDataAdapter.SelectCommand=$oMYSQLCommand;
# Execute the query
$count=$oMYSQLDataAdapter.Fill($oMYSQLDataSet, "data");

$result = $oMYSQLDataSet.Tables[0].Rows[0]["Count"];

write-host $result;

Rezultat

U ovom članku je prikazan primjer pokazatelja performansi (elementi podataka) u Zabbixu. Ovaj pristup omogućava obavještavanje administratora o raznim problemima u stvarnom vremenu ili nakon određenog vremena. Na taj način, ovaj pristup pomaže minimizirati mogućnost pojave kritičnih problema i zaustavljanja rada DBMS-a i servera, što zauzvrat štiti proizvodnju od zaustavljanja radnih procesa.
Prethodni članak: Reglamentni radovi s bazom podataka informacijskog sustava 24×7 u MS SQL Serveru

Izvori:

» Zabbix 3.4
» Pokazatelji performansi
» Centar za performanse za Azure SQL bazu podataka i SQL Server Database Engine
» SQL način života
» SQLSkills
» TechNet Microsoft
» Analiziramo korištenje memorije
» Analiza performansi
» Dokumentacija o SQL-u
» Bilješke o Windows-u

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster