Përdorimi i Zabbix për monitorimin e bazës së të dhënave MS SQL Server

Parathënie

Shpesh lind nevoja për të njoftuar administratorin në kohë reale për problemet që lidhen me DB (bazën e të dhënave).

Në këtë artikull do të përshkruhet se çfarë duhet të konfigurohet në Zabbix për monitorimin e bazës së të dhënave MS SQL Server.

Ju tërheq vëmendjen se nuk do të jepet një udhëzim i detajuar hap pas hapi për konfigurimin, por në këtë artikull do të gjeni formulat, rekomandimet e përgjithshme, si dhe një përshkrim të hollësishëm për shtimin e elementeve të personalizuara të të dhënave përmes procedurave të ruajtura.
Gjithashtu, këtu do të shqyrtohen vetëm numëruesit kryesorë të performancës.

Zgjidhja

Fillimisht do të përshkruaj të gjithë ata numërues të performancës (përmes elementeve të të dhënave në Zabbix) që na duhen:

  1. Logical Disk
    1. Avg Disc sec/Read
      Tregon kohën mesatare të leximit të të dhënave nga disku, të shprehur në sekonda. Vlera mesatare e numëruesit të performancës Avg. Disk sec/Read nuk duhet të kalojë 10 milisekonda. Vlera maksimale e numëruesit të performancës Avg. Disk sec/Read nuk duhet të kalojë 50 milisekonda.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read], gjithashtu është e rëndësishme të monitorohet disku i nevojshëm, për shembull kështu: perf_counter[LogicalDisk(C:)Avg. Disk sec/Read]

      Shembuj të trigger-ëve:
      {НАЗВАНИЕ_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.005, niveli-i lartë
      dhe
      {НАЗВАНИЕ_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.0025, niveli-mesatar

    2. Avg Disc sec/Write
      Tregon kohën mesatare të shkrimit të të dhënave në disk, të shprehur në sekonda. Vlera mesatare e numëruesit të performancës Avg. Disk sec/Write nuk duhet të kalojë 10 milisekonda. Vlera maksimale e numëruesit të performancës Avg. Disk sec/Write nuk duhet të kalojë 50 milisekonda.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write], gjithashtu është e rëndësishme të monitorohet disku i nevojshëm, për shembull kështu: perf_counter[LogicalDisk(C:)Avg. Disk sec/Write]

      Shembuj të trigger-ëve:
      {НАЗВАНИЕ_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.005, niveli-i lartë
      dhe
      {НАЗВАНИЕ_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.0025, niveli-mesatar

    3. Avg Disk Queue Length

      Gjatësia mesatare e radhës së kërkesave për diskun. Tregon numrin e kërkesave për diskun që presin të përpunohen gjatë një intervali të caktuar kohe. Normale konsiderohet një radhë jo më e madhe se 2 për një disk të vetëm. Nëse në radhë ka më shumë se dy kërkesa, disku mund të jetë i mbingarkuar dhe të mos arrijë të përpunojë kërkesat që vijnë. Për të saktësuar se me cilat operacione konkretisht disku nuk po përballon ngarkesën, mund të përdoren numëruesit Avg. Disk Read Queue Length (radha e kërkesave për lexim) dhe Avg. Disk Wright Queue Length (radha e kërkesave për shkrim).
      Vlera Avg. Disk Queue Length nuk matet drejtpërdrejt, por llogaritet sipas ligjit të Little nga teoria matematikore e radhëve. Sipas këtij ligji, numri i kërkesave që presin përpunim është mesatarisht i barabartë me frekuencën e ardhjes së kërkesave, të shumëzuar me kohën e përpunimit të kërkesës. Pra, në rastin tonë Avg. Disk Queue Length = (Disk Transfers/sec) * (Avg. Disk sec/Transfer).

      Avg. Disk Queue Length paraqitet si një nga numëruesit kryesorë për përcaktimin e ngarkesës së nënsistemit të diskut, por për një vlerësim të saktë të tij duhet kuptuar qartë struktura fizike e sistemit të ruajtjes. Për shembull, për një hard disk të vetëm kritik konsiderohet vlera mbi 2, ndërsa nëse disku ndodhet në një varg RAID me 4 disqe, shqetësimi duhet të nisë kur vlera kalon 4*2=8.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk Queue Length], si dhe është e rëndësishme të monitorohet disku i nevojshëm, për shembull kështu: perf_counter[LogicalDisk(C:)Avg. Disk Queue Length]

  2. Memorie
    1. Faqe/sek
      Tregon numrin e faqeve që SQL Server i ka lexuar nga disku ose i ka shkruar në disk për të përpunuar kërkesat ndaj faqeve të memories që në momentin e thirrjes nuk ishin ngarkuar në RAM. Kjo vlerë është shuma e treguesve Pages Input/sec dhe Pages Output/sec, si dhe përfshin paging-un (swap) të memories cache të sistemit për akses në skedarët e të dhënave të aplikacioneve. Përveç kësaj, këtu përfshihet edhe paging-u i skedarëve pa cache që mapohen drejtpërdrejt në memorie. Ky është treguesi kryesor që duhet monitoruar nëse vërehet ngarkesë e lartë në përdorimin e memories dhe si pasojë shkëmbim i tepërt i faqeve. Ky numërues tregon nivelin e swap-it dhe vlera e tij normale (jo në pikut) duhet të jetë afër zeros. Rritja e swap-it tregon nevojën për të shtuar RAM ose për të ulur numrin e aplikacioneve që ekzekutohen në server.

      Zabbix: perf_counter[MemoryPages/sec]
      Shembull i trigger-it:
      {НАЗВАНИЕ_УЗЛА:perf_counter[MemoryPages/sec].min(5m)}>1000, niveli-informacion

    2. Page Faults/sec

      Kjo është vlera e numëruesit të gabimeve të faqes. Një gabim faqeje ndodh kur një proces i referohet një faqeje të memories virtuale që nuk ndodhet në grupin aktiv të RAM-it. Ky numërues përfshin si ato gabime faqeje që kërkojnë qasje në disk, ashtu edhe ato që shkaktohen kur faqja ndodhet jashtë grupit aktiv në RAM. Shumica e procesorëve mund t'i përpunojnë gabimet e llojit të dytë pa vonesa të dukshme. Megjithatë, përpunimi i gabimeve të llojit të parë, që kërkojnë qasje në disk, mund të sjellë vonesa të konsiderueshme.

      Zabbix: perf_counter[MemoryPage Faults/sec]
      Shembull i trigger-it:
      {НАЗВАНИЕ_УЗЛА:perf_counter[MemoryPage Faults/sec].min(5m)}>1000, niveli-informacion

    3. Available Bytes

      Monitoron sasinë e memories së disponueshme në bajte për ekzekutimin e proceseve të ndryshme. Vlerat e ulëta tregojnë mungesë memorieje. Zgjidhja është rritja e memories. Në shumicën e rasteve, ky numërues duhet të jetë vazhdimisht mbi 5000 KB.
      Ka kuptim të vendoset pragu për Available Mbytes manualisht, për arsyet e mëposhtme:

      • 50% memorie e lirë në dispozicion = Shkëlqyeshëm
      • 25% memorie në dispozicion = Kërkon vëmendje
      • 10% e lirë = Mund të ketë probleme
      • Më pak se 5% memorie në dispozicion = Kritike për shpejtësinë, kërkohet ndërhyrje.
      Zabbix: perf_counter[MemoryAvailable Bytes]

  3. Processor (Total): % Processor Time
    Ky numërues tregon përqindjen e kohës gjatë së cilës procesori ka qenë i zënë me ekzekutimin e operacioneve për fijet jo të papuna (non-Idle thread). Kjo vlerë mund të konsiderohet si pjesa e kohës që i kushtohet kryerjes së punës së dobishme. Çdo procesor mund t'i caktohet një fije e papunë, e cila konsumon cikle joproduktive të procesorit që nuk përdoren nga fijet e tjera. Për këtë numërues janë tipike kulmet e shkurtra që mund të arrijnë 100 për qind. Megjithatë, nëse vërehen periudha të gjata kur shfrytëzimi i procesorit është mbi 80 për qind, sistemi do të jetë më efikas nëse përdor më shumë procesorë.

    Zabbix: perf_counter[Processor(_Total)% Processor Time], këtu gjithashtu mund të shfaqet sipas bërthamave
    Shembull i trigger-it:
    {НАЗВАНИЕ_УЗЛА:perf_counter[Processor(_Total)% Processor Time].min(5m)}>80, niveli-informacion

  4. Network Interface (*): % bajte gjithsej/sek
    Numri i përgjithshëm i bajteve të dërguara dhe të marra për sekondë në të gjitha ndërfaqet. Kjo është gjerësia e brezit të ndërfaqes (në bajte). Duhet të krahasoni vlerën e këtij numëruesi me gjerësinë maksimale të brezit të kartës së rrjetit. Në përgjithësi, ky numërues nuk duhet të tregojë më shumë se 50% të shfrytëzimit të gjerësisë së brezit të adaptorit të rrjetit.
    Zabbix: perf_counter[Network Interface(*)Bytes Sent/sec]
  5. MS SQL Server: Metodat e hyrjes
    Objekti Access Methods (Metodat e hyrjes) në SQL Server ofron numërues që ndihmojnë në monitorimin e qasjes te të dhënat logjike brenda bazës së të dhënave. Qasja fizike te faqet e bazës së të dhënave në disk kontrollohet me ndihmën e numëruesve të menaxherit të buffer-it. Monitorimi i metodave të qasjes te të dhënat në bazën e të dhënave ndihmon për të përcaktuar nëse performanca e pyetjeve mund të rritet duke shtuar ose ndryshuar indekset, duke shtuar ose zhvendosur seksione, duke shtuar skedarë ose grupe skedarësh, duke defragmentuar indekset ose duke ndryshuar tekstin e pyetjeve. Përveç kësaj, me ndihmën e numëruesve të objektit Access Methods mund të monitorohen madhësia e të dhënave, indekset dhe hapësira e lirë në bazën e të dhënave, duke kontrolluar vëllimin dhe fragmentimin për çdo instancë të serverit. Fragmentimi i tepërt i indekseve mund të ulë ndjeshëm performancën.
    1. Ndarje faqesh/sek
      Numri i ndarjeve të faqeve në sekondë, të kryera si rezultat i mbushjes së tepërt të faqeve të indeksit. Një vlerë e lartë e këtij treguesi do të thotë se gjatë operacioneve të futjes dhe ndryshimit të të dhënave, SQL Server detyrohet të kryejë shumë operacione që konsumojnë burime për ndarjen e faqeve dhe zhvendosjen e një pjese të faqes ekzistuese në një vend të ri. Këto operacione, sa herë që është e mundur, duhen shmangur. Problemi mund të tentohet të zgjidhet në dy mënyra:
      — të krijohet një indeks i klasterizuar për kolonat me rritje automatike. Në këtë rast, regjistrimet e reja nuk do të vendosen brenda faqeve tashmë të zëna me të dhëna, por do të zënë faqet e reja në mënyrë të njëpasnjëshme;
      — të rindërtohen indekset duke rritur vlerën e parametrit Fillfactor. Ky parametër lejon rezervimin e hapësirës së lirë në faqet e indekseve, e cila do të përdoret për vendosjen e të dhënave të reja pa pasur nevojë të kryhen operacione të ndarjes së faqeve.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Access MethodsPage Splits/sec»,30]
      Shembull i trigger-it: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Access MethodsPage Splits/sec»,30].last()}>{НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:SQL StatisticsBatch Requests/sec»,30].last()}/5, niveli-informacion
    2. Full Scans/sec
      Numri i operacioneve të pakufizuara të skanimit të plotë në sekondë. Këto operacione përfshijnë skanimin e tabelës kryesore dhe skanimin e plotë të indeksit. Rritja e qëndrueshme e këtij treguesi mund të sinjalizojë degradim të sistemit (mungesë e indekseve të nevojshme, fragmentim i lartë i tyre, mospërdorim nga optimizuesi i indekseve ekzistuese, prania e indekseve të papërdorura). Megjithatë, duhet theksuar se skanimi i plotë në tabela të vogla nuk është gjithmonë i keq, sepse nëse e gjithë tabela mund të vendoset në RAM, atëherë pikërisht skanimi i plotë do të jetë më i shpejtë. Por në shumicën e rasteve, rritja e qëndrueshme e treguesit të këtij numëruesi do të tregojë degradim të sistemit. E gjithë kjo vlen vetëm për sistemet OLTP. Në sistemet OLAP, skanimet e plota të vazhdueshme janë normale.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Access MethodsFull Scans/sec»,30]

  6. MS SQL Server: Buffer Manager
    Objekti Buffer Manager (menaxheri i buffer-it) ofron numërues që lejojnë të monitorohet se si SQL Server përdor burimet e mëposhtme:
    — memoria për ruajtjen e faqeve të të dhënave;
    — numërues që përdoren për monitorimin e hyrje-daljes fizike kur SQL Server lexon dhe shkruan faqet e bazës së të dhënave;
    — zgjerim i buffer pool për të zmadhuar cache-in e buferit duke përdorur memorie të shpejtë jo të paqëndrueshme, si p.sh. disqe SSD;
    — monitorimi i memories dhe i numëruesve që përdor SQL Server ndihmon për të marrë informacionin e mëposhtëm;
    — nëse ka “bottleneck”-e të shkaktuara nga mungesa e memories fizike. Nëse të dhënat e përdorura shpesh nuk mund të ruhen në cache, SQL Server detyrohet t’i lexojë ato nga disku;
    — nëse mund të rritet efikasiteti i ekzekutimit të pyetjeve duke shtuar sasinë e memories ose duke caktuar memorie shtesë për cache-imin e të dhënave apo ruajtjen e strukturave të brendshme të SQL Server;
    — sa shpesh SQL Server i lexon të dhënat nga disku. Krahasuar me operacione të tjera, siç është qasja në memorie, hyrje-dalja fizike kryhet më ngadalë. Zvogëlimi i volumit të hyrje-daljes mund të rrisë performancën e ekzekutimit të pyetjeve.
    1. Raporti i goditjeve të Buffer Cache
      Tregon sa mirë SQL Server arrin t’i mbajë të dhënat në buffer cache. Sa më e lartë të jetë kjo vlerë, aq më mirë, sepse për qasje efikase të SQL Server te faqet e të dhënave, ato duhet të ndodhen në buffer cache dhe operacionet e hyrje-daljes fizike (I/O) duhet të mungojnë. Nëse vërehet një rënie e qëndrueshme e vlerës mesatare të këtij numëruesi, duhet të merret në konsideratë shtimi i RAM. Ky tregues duhet të jetë gjithmonë mbi 90% për sistemet OLTP dhe mbi 50% për sistemet OLAP.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer ManagerBuffer cache hit ratio»,30]
      Shembuj të trigger-ëve: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer ManagerBuffer cache hit ratio»,30].last()}<70, niveli-i-lartë
      dhe
      {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer ManagerBuffer cache hit ratio»,30].last()}<80, niveli-mesatar
    2. Jetëgjatësia e faqes
      Tregon sa gjatë faqja do të qëndrojë vazhdimisht në memorie në gjendjen aktuale. Nëse vlera bie vazhdimisht, kjo do të thotë se sistemi po e mbingarkon buffer pool-in. Si rezultat, funksionimi i memories mund të shkaktojë probleme që çojnë në ulje të performancës. Vlen të theksohet se nuk ekziston një tregues universal, nën të cilin të mund të konkludohet pa mëdyshje se sistemi po e mbingarkon buffer pool-in (vlera 300 sekonda është e vjetëruar që nga MS SQL Server 2012).
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer ManagerPage life expectancy»,30]
      Shembull i trigger-it: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer ManagerPage life expectancy»,30].last()}<5, niveli-informacion

  7. MS SQL Server: Statistika të përgjithshme
    Objekti General Statistics (Statistika të përgjithshme) në SQL Server ofron numërues që lejojnë monitorimin e aktivitetit të përgjithshëm të serverit, si p.sh. numrin e lidhjeve të njëkohshme dhe numrin e përdoruesve për sekondë që lidhen ose shkëputen nga kompjuteri ku është ekzekutuar instanca e SQL Server. Këta tregues janë të dobishëm për përdorim në sisteme të mëdha të përpunimit operacional të transaksioneve (OLTP), ku një numër i madh klientësh lidhen dhe shkëputen vazhdimisht nga instanca e SQL Server.
    1. Procese të bllokuara
      Numri i proceseve të bllokuara aktualisht.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30]
      Shembull i trigger-it: ({НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30].min(2m,0)}>=0)
      and ({НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30].time(0)}>=50000)
      and ({НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30].time(0)}<=230000), niveli-informacion (këtu zbatohet kufizimi i sinjalizimit nga ora 05:00 deri në 23:00)
    2. Lidhjet e përdoruesve
      Numri i përdoruesve të lidhur aktualisht me serverin SQL Server.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General StatisticsUser Connections»,30]

  8. MS SQL Server: Locks
    Objekti Locks (Bllokimet) në Microsoft SQL Server ofron informacion për bllokimet e SQL Server të marra për lloje të veçanta burimesh. Bllokimet vendosen mbi burime të SQL Server, si p.sh. rreshtat e lexuar ose të ndryshuar nga një transaksion, për të parandaluar përdorimin e njëkohshëm të burimeve nga disa transaksione. Për shembull, nëse një bllokim ekskluziv (X) është marrë nga një transaksion mbi një rresht në tabelë, asnjë transaksion tjetër nuk do të mund ta ndryshojë atë rresht derisa bllokimi të lirohet. Minimizimi i përdorimit të bllokimeve rrit paralelizmin, gjë që mund të përmirësojë performancën e përgjithshme. Mund të monitorohen njëkohësisht disa instanca të objektit Locks, ku secila do të përfaqësojë një bllokim për një lloj të veçantë burimi.
    1. Koha mesatare e pritjes (ms)
      Kohëzgjatja mesatare e pritjes (në milisekonda) për të gjitha kërkesat për bllokim që kanë kërkuar pritje. Ky numërues tregon sa kohë, mesatarisht, proceset e përdoruesve kalojnë në radhë për të vendosur një bllokim mbi një burim. Vlera maksimale e pranueshme e këtij numëruesi varet plotësisht nga ngarkesa dhe detyra juaj, ndaj është e vështirë të përcaktohet një vlerë mesatare e përgjithshme për të gjitha aplikacionet. Një vlerë tepër e lartë e këtij numëruesi mund të tregojë probleme me bllokimet në bazën tuaj të të dhënave.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Average Wait Time (ms)»,30]
      Shembull i trigger-it: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Average Wait Time (ms)»,30].last()}>=500, nivel informacioni
    2. Koha e pritjes së bllokimit (ms)
      Koha totale e pritjes për bllokimet (në milisekonda) gjatë sekondës së fundit.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Lock Wait Time (ms)»,30]
    3. Pritje për bllokim/sek
      Numri i rasteve gjatë sekondës së fundit kur një rrjedhë duhej të priste për shkak të një kërkese për bllokim.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Lock Waits/sec»,30]
    4. Skadime kohe të bllokimit/sek
      Numri i përsëritjeve kur bllokimi nuk mund të merret përmes qarkullimit ciklik. Vlera e parametrit të konfigurimit SQL Server spin counter përcakton numrin e "rrotullimeve" të rrjedhës (spins) përpara se të skadojë koha e pritjes dhe rrjedha të kalojë në gjendje joaktive.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Lock Timeouts/sec»,30]
      Shembull i trigger-it: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Locks(_Total)Lock Timeouts/sec»,30].last()}>=1000, nivel informacioni
    5. Kërkesa për bllokim/sek
      Numri i kërkesave për sekondë për llojin e specifikuar të bllokimit.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Lock Requests/sec»,30]
      Shembull i trigger-it: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Lock Requests/sec»,30].last()}>500000, niveli-informacion
    6. Lock Number of Deadlocks/sec
      Numri i kërkesave për bllokim në sekondë që çojnë në deadlock. Prania e deadlock-eve tregon se kërkesat janë ndërtuar gabim dhe bllokojnë burimet e përbashkëta.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Number of Deadlocks/sec»,30]
      Shembull i trigger-it: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)Number of Deadlocks/sec»,30].last()}>1, niveli-lartë

  9. MS SQL Server: Memory Manager
    Objekti Memory Manager në Microsoft SQL Server ofron numërues për monitorimin e përdorimit të memories së të gjithë serverit. Monitorimi i përdorimit të memories së serverit për të vlerësuar veprimet e përdoruesve dhe përdorimin e burimeve mund të ndihmojë në identifikimin e mungesave të performancës. Monitorimi i memories së përdorur nga instanca e SQL Server mund të ndihmojë në përcaktimin e sa vijon:
    — nëse ka mungesë të memories fizike për ruajtjen në cache të të dhënave që përdoren shpesh. Nëse memoria nuk mjafton, SQL Server duhet t'i marrë të dhënat nga disku;
    — nëse performanca e kërkesave mund të përmirësohet nëse shtohet memoria ose rritet sasia e memories së disponueshme për ruajtjen në cache të të dhënave ose të strukturave të brendshme të SQL Server.
    1. Memory Grants Outstanding
      Tregon numrin total të proceseve që kanë marrë me sukses memorien e hapësirës së punës. Nëse treguesi bie vazhdimisht, duhet rritur RAM-i.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Memory ManagerMemory Grants Outstanding»,30]
    2. Memory Grants Pending
      Tregon numrin total të proceseve që presin t’u caktohet memoria e hapësirës së punës. Nëse treguesi rritet vazhdimisht, duhet rritur RAM-i.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Memory ManagerMemory Grants Pending»,30]

  10. MS SQL Server: Statistics
    Objekti Statistics në Microsoft SQL Server siguron funksionimin e numëruesve për monitorimin e kompilimit dhe të llojeve të kërkesave që i dërgohen instancës së SQL Server. Monitorimi i numrit të kompilimeve dhe rikompilimeve të kërkesave, si dhe i numrit të paketave të marra nga instanca e SQL Server, jep një pasqyrë se sa shpejt SQL Server përpunon kërkesat e përdoruesve dhe sa me efikasitet i trajton ato optimizuesi i kërkesave.
    1. Batch Requests/sec
      Numri i paketave të komandave Transact-SQL të marra për sekondë. Në këtë statistikë ndikojnë çdo lloj kufizimi (hyrje/dalje, numri i përdoruesve, madhësia e cache-it, kompleksiteti i pyetjeve etj.). Një numër i lartë i kërkesave Batch tregon për throughput të lartë.
      Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:SQL StatisticsBatch Requests/sec»,30]

Përveç të gjitha sa u përmendën më sipër, mund të konfigurohen edhe elementë të tjerë të të dhënave (si edhe të krijohen triggera për ta me njoftim të mëvonshëm). Për shembull:
1) madhësia e hapësirës së lirë në disk
2) madhësitë e skedarëve të të dhënave të DB dhe të skedarit të log-ut
etj.
Megjithatë, të gjithë këta tregues nuk e pasqyrojnë pikërisht problemin e pyetjeve në kohë reale.
Për këtë është e nevojshme të krijohen numërues të posaçëm.
Për arsye konfidencialiteti, nuk do të jap shembuj të tillë numëruesish. Aq më tepër që ato konfigurohen në mënyrë unike për çdo sistem. Por vlen të theksohet se për sisteme si 1С, NAV dhe CRM, numërues të specializuar mund të krijohen së bashku me zhvilluesit përkatës.
Po jap një shembull të krijimit të një treguesi të përgjithshëm, i cili tregon sa pyetje po ekzekutohen dhe sa pyetje po presin për ekzekutim (janë të pezulluara ose të bllokuara) në çdo moment kohe.
Për këtë duhet të krijoni një procedurë të ruajtur:
Kodi

USE [ИМЯ_БАЗЫ_ДАННЫХ]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [nav].[ZabbixGetCountRequestStatus]
	@Status nvarchar(255)
AS
BEGIN
	/*
		kthen numrin e pyetjeve me statusin e caktuar
	*/
	SET NOCOUNT ON;

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

Më pas duhet të hyni në dosjen ku ndodhet Zabbix (zabbixconfuserparams.d) dhe të krijoni 2 skedarë me prapashtesën ps1 (PowerShell), duke shkruar në secilin prej tyre kodet e mëposhtme:
Kodi për pyetjet në ekzekutim

$SQLServer = "EMRI_I_INSTANCËS";
$uid = "HYRJA"; 
$pwd = "FJALËKALIMI";
$Status="running";

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

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

#Krijojmë një kërkesë direkt në 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;

Kodi për kërkesat në pritje

$SQLServer = "EMRI_I_INSTANCËS";
$uid = "HYRJA"; 
$pwd = "FJALËKALIMI";
$Status="suspended";

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

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

#Krijojmë një kërkesë direkt në 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;

Tani duhet të krijoni një skedar me parametra të personalizuar dhe me prapashtesën .conf (ose të shtoni rreshtat në një skedar të tillë ekzistues, nëse është krijuar më parë) dhe të vendosni rreshtat e mëposhtëm:
UserParameter=EMRI_I_PARAMETRIT_NUMRI_I_KËRKESAVE_NË_EKZEKUTIM,powershell -NoProfile -ExecutionPolicy Bypass -File RRUGA_E_PLOTËzabbixconfuserparams.dEMRI_I_SKEDARIT_PËR_KËRKESAT_NË_EKZEKUTIM.ps1
UserParameter=EMRI_I_PARAMETRIT_NUMRI_I_KËRKESAVE_NË_PRITJE,powershell -NoProfile -ExecutionPolicy Bypass -File RRUGA_E_PLOTËzabbixconfuserparams.dEMRI_I_SKEDARIT_PËR_KËRKESAT_NË_PRITJE.ps1
Pas kësaj, ruani skedarin .conf dhe rinisni agjentin Zabbix.
Më pas, shtoni dy elementë të rinj në Zabbix (në këtë rast emrat dhe çelësat përputhen):
EMRI_I_PARAMETRIT_NUMRI_I_KËRKESAVE_NË_EKZEKUTIM
EMRI_I_PARAMETRIT_NUMRI_I_KËRKESAVE_NË_PRITJE
Tani mund të krijoni grafikë dhe trigerë për elementët e personalizuar të të dhënave të krijuara.

Nëse numri i kërkesave në pritje rritet ndjeshëm, me kërkesën e mëposhtme mund të shfaqni të gjitha kërkesat që po ekzekutohen dhe që janë në pritje në atë moment, me detaje se nga ku dhe nën cilin login po ekzekutohet kërkesa, tekstin dhe planin e kërkesës, si dhe hollësi të tjera:
Kodi

/*Активные, готовые к выполнению и ожидающие запросы, а также те, что явно блокируют другие сеансы*/
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);

Gjithashtu, ju kujtoj se nga statistikat e mbledhura mund të identifikohen kërkesat më të rënda:
Kodi

/*
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

Mund të shkruhet edhe për MySQL. Për këtë duhet të instaloni mysql-connector-net dhe më pas të shkruani afërsisht një kod të tillë:
Kodi për kërkesat në pritje

#Задаем переменные для подключение к 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;

Rezultati

Në këtë artikull u shqyrtua një shembull i numëruesve të performancës (elementeve të të dhënave) në Zabbix. Kjo qasje u mundëson administratorëve të njoftohen për probleme të ndryshme në kohë reale ose pas një periudhe të caktuar. Në këtë mënyrë, kjo qasje ndihmon në minimizimin e rrezikut të shfaqjes së një problemi kritik në të ardhmen dhe të ndalimit të punës së DBMS dhe serverit, duke mbrojtur kështu proceset e biznesit nga ndërprerja.
Artikulli i mëparshëm: Mirëmbajtja e planifikuar e bazës së të dhënave të sistemit informativ 24×7 në MS SQL Server

Burimet:

» Zabbix 3.4
» Numëruesit e performancës
» Qendra e performancës për bazën e të dhënave Azure SQL dhe SQL Server Database Engine
» Stili i jetës SQL
» SQLSkills
» TechNet Microsoft
» Analizojmë përdorimin e memories
» Analiza e performancës
» Dokumentacioni i SQL
» Shënime rreth Windows

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster