Përdorimi i Zabbix për të monitoruar bazën e të dhënave të MS SQL Server

Parathënie libri

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

Ky artikull do të përshkruajë se çfarë duhet të konfigurohet në Zabbix për të monitoruar bazën e të dhënave MS SQL Server.

Unë tërheq vëmendjen tuaj për faktin se në detaje se si të konfiguroni nuk do të jepet, megjithatë, formula dhe rekomandime të përgjithshme, si dhe një përshkrim i hollësishëm i shtimit të elementeve të të dhënave me porosi përmes procedurave të ruajtura do të jepen në këtë artikull.
Gjithashtu, këtu do të merren parasysh vetëm numëruesit kryesorë të performancës.

vendim

Së pari, unë do të përshkruaj të gjithë ata numërues të performancës (nëpërmjet artikujve në Zabbix) që na duhen:

  1. Disku logjik
    1. Mesatarja e sekondës/Leximit të diskut
      Tregon kohën mesatare në sekonda për të lexuar të dhënat nga disku. Vlera mesatare e numëruesit të performancës mesatare. Sec/leximi i diskut nuk duhet të kalojë 10 milisekonda. Vlera maksimale e numëruesit të performancës mesatare. Sec/leximi i diskut nuk duhet të kalojë 50 milisekonda.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read], dhe është gjithashtu e rëndësishme të mbani gjurmët e diskut të dëshiruar, për shembull: perf_counter[LogicalDisk(C:)Avg. Disku sek/lexo]

      Shembuj nxitës:
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.005, niveli i lartë
      и
      {NOTE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.0025, niveli-mesatar

    2. Mesatarja e sekondës/Shkrimit të diskut
      Tregon kohën mesatare në sekonda për të shkruar të dhëna në disk. Vlera mesatare e numëruesit të performancës mesatare. Sec/Write në disk nuk duhet të kalojë 10 milisekonda. Vlera maksimale e numëruesit të performancës mesatare. Disk sec/Write nuk duhet të kalojë 50 milisekonda.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write], dhe është gjithashtu e rëndësishme të mbani gjurmët e diskut të dëshiruar, për shembull: perf_counter[LogicalDisk(C:)Avg. Disk sekondë/Shkruaj]

      Shembuj nxitës:
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.005, niveli i lartë
      и
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.0025, niveli-mesatar

    3. Gjatësia mesatare e radhës së diskut

      Gjatësia mesatare e radhës së kërkesës në disk. Shfaq numrin e kërkesave të diskut në pritje gjatë një intervali kohor të caktuar. Radha normale nuk është më shumë se 2 për një disk të vetëm. Nëse ka më shumë se dy kërkesa në radhë, atëherë disku me siguri është i mbingarkuar dhe nuk ka kohë për të përpunuar kërkesat hyrëse. Ju mund të përdorni numëruesit mesatarë për të zbuluar saktësisht se çfarë operacionesh nuk mund të përballojë disku. Gjatësia e radhës së leximit të diskut (radha e kërkesës për lexim) dhe mesatare. Disk Wright Queue Length (radha e kërkesës për shkrim).
      Vlera mesatare. Gjatësia e radhës së diskut nuk matet, por llogaritet sipas ligjit të Little nga teoria matematikore e radhëve. Sipas këtij ligji, numri i kërkesave që presin për t'u trajtuar mesatarisht është i barabartë me shpeshtësinë e kërkesave të pranuara, shumëzuar me kohën e shqyrtimit të kërkesës. Ato. në rastin tonë Mes. Gjatësia e radhës së diskut = (Transferimet e diskut/sek) * (mesatarja e sek./Transferimit të diskut).

      gusht Gjatësia e radhës së diskut jepet si një nga numëruesit kryesorë për të përcaktuar ngarkesën e punës së nënsistemit të diskut, megjithatë, për ta vlerësuar atë në mënyrë adekuate, është e nevojshme të përfaqësohet me saktësi struktura fizike e sistemit të ruajtjes. Për shembull, për një hard disk të vetëm, një vlerë më e madhe se 2 konsiderohet kritike, dhe nëse disku ndodhet në një grup RAID me 4 disqe, atëherë duhet të shqetësoheni nëse vlera është më e madhe se 4 * 2 = 8.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk Queue Length], dhe është gjithashtu e rëndësishme të mbani gjurmët e diskut të dëshiruar, për shembull: perf_counter[LogicalDisk(C:)Avg. Gjatësia e radhës së diskut]

  2. kujtim
    1. Faqe/sek
      Tregon numrin e faqeve që SQL Server lexoi nga disku ose shkroi në disk për të zgjidhur akseset në faqet e memories që nuk ishin ngarkuar në memorien kryesore në kohën e aksesit. Kjo vlerë është shuma e vlerave të Pages Input/sek dhe Pages Output/sek, dhe gjithashtu merr parasysh paging (ndërrim/këmbim) të cache-it të sistemit për të aksesuar skedarët e të dhënave të aplikacionit. Ai gjithashtu përfshin faqezim të skedarëve të pa-memorizuar drejtpërdrejt të hartës së memories. Ky është numëruesi kryesor për t'u parë nëse jeni duke përjetuar përdorim të lartë të memories dhe faqezim të tepruar të lidhur. Ky numërues karakterizon sasinë e shkëmbimit dhe vlera e tij normale (jo kulmi) duhet të jetë afër zeros. Një rritje në shkëmbim tregon nevojën për të rritur RAM ose për të zvogëluar numrin e aplikacioneve që funksionojnë në server.

      Zabbix: perf_counter[MemoryPages/sek] Shembull i shkas:
      {NOTE_NAME:perf_counter[MemoryPages/sec].min(5m)}>1000, informacione për nivelin

    2. Gabimet e faqes/sek

      Kjo është vlera e numëruesit të gabimeve të faqes. Një gabim faqeje ndodh kur një proces referon një faqe memorie virtuale që nuk është në grupin e punës të RAM-it. Ky numërues merr parasysh si ato defekte të faqes që kërkojnë qasje në disk dhe ato të shkaktuara nga faqja jashtë grupit të punës në RAM. Shumica e procesorëve mund të trajtojnë gabimet e faqeve të tipit XNUMX pa shumë vonesë. Megjithatë, trajtimi i gabimeve të faqeve të tipit XNUMX, të cilat kërkojnë qasje në disk, mund të shkaktojnë vonesa të konsiderueshme.

      Zabbix: perf_counter[Defektet e faqes së kujtesës/sek] Shembull i shkas:
      {NODE_NAME:perf_counter[MemoryPage Faults/sec].min(5m)}>1000, informacione për nivelin

    3. Bajtet e disponueshme

      Mban gjurmët e sasisë së memories në bajt të disponueshme për procese të ndryshme për t'u ekzekutuar. Numrat e ulët do të thotë memorie e ulët. Zgjidhja është rritja e kujtesës. Ky njehsor në shumicën e rasteve duhet të jetë vazhdimisht mbi 5000 kV.
      Ka kuptim të vendosni pragun për Mbajt të disponueshëm manualisht për arsyet e mëposhtme:

      •50% memorie e lirë në dispozicion = E shkëlqyeshme
      •25% memorie e disponueshme = Ka nevojë për vëmendje
      •10% falas = Probleme të mundshme
      • Më pak se 5% memorie e disponueshme = Kritike për shpejtësinë, duhet të ndërhyni.
      Zabbix: perf_counter [memorie Bytes të disponueshme]

  3. Procesori (Total): % Koha e procesorit
    Ky numërues tregon përqindjen e kohës që procesori ishte i zënë me ekzekutimin e operacioneve për thread-et jo boshe (thread jo-idle). Kjo vlerë mund të konsiderohet si një pjesë e kohës së nevojshme për të kryer punë të dobishme. Çdo procesor mund t'i caktohet një thread boshe që konsumon cikle procesori joproduktive që nuk përdoren nga thread-ët e tjerë. Ky numërues karakterizohet nga maja të shkurtra që mund të arrijnë 100 për qind. Megjithatë, nëse ka periudha të zgjatura kur përdorimi i procesorit është mbi 80 përqind, atëherë sistemi do të jetë më efikas kur përdor më shumë procesorë.

    Zabbix: perf_counter[Processor(_Total)% Processor Time], këtu mund të shfaqet edhe sipas bërthamave
    Shembull i shkas:
    {NODE_NAME:perf_counter[Processor(_Total)% Processor Time].min(5m)}>80, niveli-info

  4. Ndërfaqja e rrjetit (*): % Bajt 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ë bajt). Është e nevojshme të krahasohet vlera e këtij numëruesi me gjerësinë maksimale të brezit të kartës së rrjetit. Në përgjithësi, ky numërues duhet të tregojë jo më shumë se 50% të përdorimit të gjerësisë së brezit të përshtatësit të rrjetit.
    Zabbix: perf_counter[Ndërfaqja e rrjetit(*)Bajt të dërguar/sek]
  5. Serveri MS SQL: Metodat e Aksesit
    Objekti i Access Methods në SQL Server ofron numërues për t'ju ndihmuar të gjurmoni aksesin në të dhënat logjike brenda një baze të dhënash. Qasja fizike në faqet e bazës së të dhënave në disk kontrollohet nga numëruesit e menaxherit të tamponit. Vëzhgimi i metodave të aksesit të të dhënave në një bazë të dhënash ju ndihmon të përcaktoni nëse mund të përmirësoni performancën e pyetjes duke shtuar ose ndryshuar indekse, duke shtuar ose lëvizur ndarje, duke shtuar skedarë ose grupe skedarësh, duke defragmentuar indekset ose duke ndryshuar tekstin e pyetjes. Ju gjithashtu mund të përdorni numëruesit në objektin Metodat e Accessit për të monitoruar madhësinë e të dhënave, indekseve dhe hapësirës së lirë në bazën e të dhënave, duke kontrolluar volumin dhe fragmentimin për çdo shembull të serverit. Fragmentimi i tepërt i indekseve mund të degradojë ndjeshëm performancën.

    1. Ndarjet e faqeve/sek
      Numri i ndërprerjeve të faqeve për sekondë që ndodhën si rezultat i tejmbushjeve të faqeve të indeksit. Një vlerë e madhe e këtij treguesi do të thotë që SQL Server kryen një numër të madh operacionesh me burime intensive për të ndarë faqet dhe për të zhvendosur një pjesë të një faqe ekzistuese në një vend të ri kur kryen operacionet e futjes dhe përditësimit. Operacione të tilla duhet të shmangen sa herë që është e mundur. Ju mund të përpiqeni ta zgjidhni problemin në dy mënyra:
      - Krijoni një indeks të grupuar në kolonat e rritjes automatike. Në këtë rast, hyrjet e reja nuk do të vendosen brenda faqeve të zëna tashmë nga të dhënat, por do të zënë në mënyrë të njëpasnjëshme faqe të reja;
      — rindërtoni indekset duke rritur vlerën e parametrit Fillfactor. Ky opsion lejon që hapësira e lirë në faqet e indeksit të rezervohet për të dhëna të reja pa pasur nevojë për faqe.
      Zabbix: perf_counter["MSSQL$InstanceName:Access MethodsPage Splits/sek",30] Shembull i shkas: {NODE_NAME:perf_counter["MSSQL$INStance_NAME:Metodat e qasjes Ndarjet e faqeve/sek",30].last()}>{NODE_NAME:perf_counter["MSSQL$INStance_NAME:SQL Statistics Kërkesa grupore/seks",(30]] /5, niveli-info
    2. Skanime të plota/sek
      Numri i skanimeve të plota të pakufizuara për sekondë. Këto operacione përfshijnë skanimet e tabelave bazë dhe skanimet e indeksit të plotë. Një rritje e qëndrueshme e këtij treguesi mund të tregojë degradim të sistemit (mungesa e indekseve të nevojshme, fragmentimi i tyre i fortë, mospërdorimi i indekseve ekzistuese nga optimizuesi, prania e indekseve të papërdorura). Sidoqoftë, vlen të përmendet se një skanim i plotë në tavolina të vogla nuk është gjithmonë i keq, sepse nëse mund ta vendosni të gjithë tabelën në RAM, atëherë do të jetë thjesht më i shpejtë për të kryer një skanim të plotë. Por në shumicën e rasteve, një rritje e qëndrueshme e këtij sporteli do të tregojë degradimin e 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$InstanceName:Access MethodsFull Scans/sek",30]

  6. MS SQL Server: Menaxher Buffer
    Objekti i Buffer Manager ofron numërues për të monitoruar se si SQL Server po përdor burimet e mëposhtme:
    - memorie për ruajtjen e faqeve të të dhënave;
    - numëruesit që përdoren për të monitoruar I/O fizike kur SQL Server lexon dhe shkruan faqet e bazës së të dhënave;
    - Zgjerimi i grupit të tamponit për të zgjeruar cache-in e tamponit duke përdorur memorie të shpejtë jo të paqëndrueshme, të tilla si disqet e gjendjes së ngurtë (SSD);
    - Monitorimi i memories dhe numëruesve të përdorur nga SQL Server ndihmon për të marrë informacionin e mëposhtëm;
    - A ka ndonjë “fyt të ngushtë” të shkaktuar nga mungesa e kujtesës fizike. Nëse të dhënat e aksesuara shpesh nuk mund të ruhen në cache, SQL Server detyrohet t'i lexojë ato nga disku;
    - Nëse është e mundur të rritet efikasiteti i ekzekutimit të pyetjeve duke rritur sasinë e memories ose duke ndarë memorie shtesë për ruajtjen e të dhënave ose ruajtjen e strukturave të brendshme të SQL Server;
    Sa shpesh SQL Server lexon të dhëna nga disku. Krahasuar me operacionet e tjera, si qasja në kujtesë, I/O fizike kërkon më shumë kohë. Reduktimi I/O mund të përmirësojë performancën e pyetjes.

    1. Buffer Cache goditi radion
      Tregon se sa plotësisht SQL Server mund të shpërndajë të dhëna në bufferin e cache-it. Sa më e lartë kjo vlerë, aq më mirë. Që SQL Server të ketë akses në mënyrë efikase në faqet e të dhënave, ato duhet të jenë në një buffer të memories dhe nuk duhet të ketë operacione fizike hyrëse/dalëse (I/O). Nëse ka një rënie të vazhdueshme në vlerën mesatare të këtij numëruesi, duhet të mendoni të shtoni RAM. Ky tregues duhet të jetë gjithmonë mbi 90% për sistemet OLTP dhe mbi 50% për sistemet OLAP.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Buffer ManagerBuffer raporti i goditjes së cache-it",30] Shembuj nxitës: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Buffer ManagerBuffer raporti i goditjes së cache",30].last()}<70, niveli i lartë
      и
      {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Buffer ManagerBuffer ratio hit cache",30].last()}<80, nivel-mesatar
    2. Jetëgjatësia e faqes
      Tregon për sa kohë faqja do të mbetet përgjithmonë në memorie në gjendjen e saj aktuale. Nëse vlera vazhdon të bjerë, kjo do të thotë se sistemi po e përdor tej mase grupin buffer. Kështu, funksionimi i kujtesës potencialisht mund të shkaktojë probleme që çojnë në degradim të performancës. Vlen të përmendet se nuk ka asnjë tregues universal nën të cilin mund të gjykohet pa mëdyshje se sistemi po abuzon me grupin e tamponit (treguesi prej 300 sekondash është i vjetëruar me MS SQL Server 2012).
      Zabbix: perf_counter["MSSQL$INSTENTION_NAME: Jetëgjatësia e faqes së menaxherit buffer",30] Shembull i shkas: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME: Jetëgjatësia e faqes së menaxherit të bufferit",30].last()}<5, niveli-info

  7. MS SQL Server: Statistikat e Përgjithshme
    Objekti i Statistikave të Përgjithshme në SQL Server ofron numërues që ju lejojnë të monitoroni aktivitetin e përgjithshëm të serverit, siç është numri i lidhjeve të njëkohshme dhe numri i përdoruesve në sekondë që lidhen ose shkëputen nga kompjuteri që ekzekuton një shembull të SQL Server. Këto metrika janë të dobishme në sistemet e përpunimit të transaksioneve të mëdha në internet (OLTP) ku një numër i madh klientësh janë vazhdimisht duke u lidhur dhe shkëputur nga shembulli i SQL Server.

    1. Procesi u bllokua
      Numri i proceseve të bllokuara aktualisht.
      Zabbix: perf_counter["MSSQL$INSPECTION_NAME:Proceset e statistikave të përgjithshme të bllokuara",30] Shembull i shkas: ({NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Proceset e statistikave të përgjithshme të bllokuara",30].min(2m,0)}>=0)
      dhe ({NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Proceset e statistikave të përgjithshme të bllokuara",30].time(0)}>=50000)
      dhe ({NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Proceset e statistikave të përgjithshme të bllokuara",30].time(0)}<=230000), informacione për nivelin (ka një kufizim alarmi nga ora 05:00 deri në orën 23:00)
    2. Lidhjet e Përdoruesit
      Numri i përdoruesve të lidhur aktualisht me SQL Server.
      Zabbix: perf_counter["MSSQL$INSPECTION_NAME: Statistikat e Përgjithshme Lidhjet e Përdoruesit",30]

  8. Serveri MS SQL: Kyçet
    Objekti Locks në Microsoft SQL Server ofron informacion rreth kyçjeve të SQL Server të marra në lloje të veçanta burimesh. Kyçet lëshohen në burimet e SQL Server, të tilla si rreshtat e lexuara ose të modifikuara nga një transaksion, për të parandaluar që transaksionet e shumta të përdorin burimet në të njëjtën kohë. Për shembull, nëse një bllokim ekskluziv (X) fitohet nga një transaksion në një rresht në një tabelë, asnjë transaksion tjetër nuk mund ta modifikojë atë rresht derisa bllokimi të lëshohet. Minimizimi i përdorimit të bravave rrit konkurencën, gjë që mund të përmirësojë performancën e përgjithshme. Instanca të shumta të objektit Locks mund të gjurmohen në të njëjtën kohë, secila prej të cilave do të përfaqësojë një bllokim në një lloj tjetër burimi.

    1. Koha mesatare e pritjes (ms)
      Koha mesatare e pritjes (në milisekonda) për të gjitha kërkesat e kyçjes që kërkonin një pritje. Ky numërues mat numrin mesatar të proceseve të përdoruesve që duhet të qëndrojnë në radhë për të marrë një bllokim në një burim. Vlera maksimale e lejuar e këtij numëruesi varet tërësisht nga detyra juaj, është e vështirë të përcaktohet një vlerë mesatare për të gjitha aplikacionet këtu. Nëse ky numërues është shumë i lartë, mund të nënkuptojë probleme me kyçjet në bazën e të dhënave tuaja.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Koha mesatare e pritjes (ms)",30] Shembull i shkas: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Koha mesatare e pritjes (ms)",30].last()}>=500, niveli-info
    2. Kyçja e kohës së pritjes (ms)
      Koha totale e pritjes së bllokimit (në milisekonda) në sekondën e fundit.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Koha e pritjes e kyçjes (ms)",30]
    3. Bllokimi Pret/sek
      Numri i herëve në sekondën e fundit që një fije duhej të priste për një kërkesë bllokimi.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Waits/sek",30]
    4. Koha e mbylljes/sek
      Numri i riprovave kur bllokimi nuk mund të merret me raunde. Vlera e parametrit të konfigurimit të numëruesit të rrotullimit të SQL Server përcakton numrin e "kthesave" të thread-it (rrotullimet) përpara se të mbarojë dhe thread të shkojë në punë.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Afatet e mbylljes/sek",30] Shembull i shkas: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Locks(_Total)Koha e mbylljes/sek",30].last()}>1000, niveli-info
    5. Kërkesat e bllokimit/sek
      Numri i kërkesave për sekondë për llojin e bllokimit të specifikuar.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Kërkesa për kyçje/sek",30] Shembull i shkas: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Kërkesat e kyçjes/sek",30].last()}>500000, niveli i informacionit
    6. Numri i bllokimit të bllokimeve/sek
      Numri i kërkesave për bllokim për sekondë që rezultojnë në një bllokim. Blloqet tregojnë pyetje të keqformuara që bllokojnë burimet e përbashkëta.
      Zabbix: perf_counter["MSSQL$INSTENTION_NAME:Numri i bllokimeve/sek",30] Shembull i shkas: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Numri i bllokimeve/sek",30].last()}>1, niveli i lartë

  9. Serveri MS SQL: Menaxheri i memories
    Objekti Memory Manager në Microsoft SQL Server ofron numërues për të monitoruar përdorimin e kujtesës në të gjithë serverin. Monitorimi i përdorimit të kujtesës në të gjithë serverin për të vlerësuar aktivitetin e përdoruesit dhe përdorimin e burimeve mund të ndihmojë në identifikimin e pengesave të performancës. Kontrolli i kujtesës i përdorur nga një shembull i SQL Server mund të ndihmojë në përcaktimin:
    - Nëse ka mungesa në memorien fizike të pamjaftueshme për të ruajtur të dhënat e aksesuara shpesh në cache. Nëse nuk ka memorie të mjaftueshme, SQL Server duhet të marrë të dhënat nga disku;
    - Nëse performanca e pyetjes mund të përmirësohet nëse shtohet më shumë memorie ose nëse disponohet më shumë memorie për ruajtjen e të dhënave ose strukturat e brendshme të SQL Server.

    1. Grantet e Kujtesës të jashtëzakonshme
      Përcakton numrin total të proceseve që kanë fituar me sukses kujtesën e hapësirës së punës. Me një rënie të qëndrueshme të treguesit, është e nevojshme të rritet RAM.
      Zabbix: perf_counter["MSSQL$INSTENTION_NAME: Memory Manager Memory Grants Outstanding",30]
    2. Grantet e kujtesës në pritje
      Tregon numrin total të proceseve që presin të jepet memoria e punës. Me një rritje të qëndrueshme të treguesit, është e nevojshme të rritet RAM.
      Zabbix: perf_counter["MSSQL$InstanceName:Memory Manager Memory Grants në pritje",30]

  10. Serveri MS SQL: Statistikat
    Objekti Statistics në Microsoft SQL Server ofron numërues për të monitoruar përpilimin dhe llojet e pyetjeve të dërguara në një shembull të SQL Server. Monitorimi i numrit të pyetjeve të përpiluara dhe të rikompiluara dhe numri i grupeve të marra nga një shembull i SQL Server ju jep një ide se sa shpejt SQL Server po ekzekuton pyetjet e përdoruesve dhe sa me efikasitet i përpunon ato optimizuesi i pyetjeve.

    1. Kërkesat e grupit/sek
      Numri i paketave të komandës Transact-SQL të marra për sekondë. Këto statistika ndikohen nga çdo kufi (I/O, numri i përdoruesve, madhësia e cache-it, kompleksiteti i pyetjes, etj.). Një numër i lartë i kërkesave për paketa tregon xhiro të lartë.
      Zabbix: perf_counter["MSSQL$InstanceName:SQL StatisticsBatch Kërkesa/sek",30]

Përveç të gjitha sa më sipër, ju gjithashtu mund të konfiguroni elementë të tjerë të të dhënave (si dhe të krijoni aktivizues mbi to me njoftimin pasues). Për shembull:
1) hapësirë ​​e lirë në disk
2) madhësitë e skedarëve të të dhënave DB dhe regjistrit të regjistrit
dhe kështu me radhë.
Megjithatë, të gjithë këta tregues nuk tregojnë problemin e pyetjes në kohë reale.
Për ta bërë këtë, ju duhet të krijoni sportelet tuaja të veçanta.
Për arsye konfidencialiteti, nuk do të jap shembuj të sporteleve të tilla. Për më tepër, ato janë konfiguruar në mënyrë unike për secilin sistem. Por unë vërej se për sisteme të tilla si 1C, NAV dhe CRM, sportelet e specializuara mund të krijohen së bashku me zhvilluesit përkatës.
Unë do të jap një shembull të krijimit të një treguesi të përgjithësuar që tregon se sa kërkesa janë duke u ekzekutuar dhe sa kërkesa janë në pritje për t'u ekzekutuar (në pauzë ose bllokuar) në çdo moment në kohë.
Për ta bërë këtë, duhet të krijoni një procedurë të ruajtur:
Kod

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

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [nav].[ZabbixGetCountRequestStatus]
	@Status nvarchar(255)
AS
BEGIN
	/*
		возвращает кол-во запросов с заданным статусом
	*/
	SET NOCOUNT ON;

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

Më pas, duhet të shkoni te dosja ku ndodhet Zabbix (zabbixconfuserparams.d) dhe të krijoni 2 skedarë me shtesën ps1 (PowerShell) dhe të shkruani kodet e mëposhtme në secilën prej tyre:
Kodi për ekzekutimin e kërkesave

$SQLServer = "НАЗВАНИЕ_ЭКЗЕМПЛЯРА";
$uid = "ЛОГИН"; 
$pwd = "ПАРОЛЬ";
$Status="running";

$connectionString = "Server = $SQLServer; Database=НАЗВАНИЕ_БД; Integrated Security = False; User ID = $uid; Password = $pwd;";

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

#Создаем запрос непосредственно к MSSQL / Create a request directly to 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 = "НАЗВАНИЕ_ЭКЗЕМПЛЯРА";
$uid = "ЛОГИН"; 
$pwd = "ПАРОЛЬ";
$Status="suspended";

$connectionString = "Server = $SQLServer; Database=НАЗВАНИЕ_БД; Integrated Security = False; User ID = $uid; Password = $pwd;";

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

#Создаем запрос непосредственно к MSSQL / Create a request directly to 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 ju duhet të krijoni një skedar me parametrat e përdoruesit me shtesën .conf (ose të shtoni rreshta në një skedar të tillë përdoruesi ekzistues nëse është krijuar më herët) dhe të futni rreshtat e mëposhtëm:
UserParameter=PARAMETER_NAME_NUMBER_of_EXECUTED_QUERY,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILE_NAME_FOR_EXECUTED_QUERY.ps1
UserParameter=PARAMETER_NAME_NUMBER_of_PENDING_REQUESTS,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILE_NAME_FOR_PENDING_REQUESTS.ps1
Pas kësaj, ruajmë skedarin .conf dhe rinisim agjentin Zabbix.
Pas kësaj, ne shtojmë dy elementë të rinj në Zabbix (në këtë rast, emrat dhe çelësi janë të njëjtë):
NAME_PARAMETER_NUMBER_PERFORMED_QUERY
NAME_PARAMETER_NUMBER_PENDING_REQUESTS
Tani mund të krijoni grafikë dhe aktivizues në artikujt e krijuar me porosi.

Nëse numri i kërkesave në pritje rritet ndjeshëm, atëherë pyetja tjetër mund të shfaqë të gjitha kërkesat në ekzekutim dhe në pritje në një kohë të caktuar me detaje se ku dhe në çfarë identifikimi është ekzekutuar kërkesa, teksti dhe plani i pyetjes, si dhe detaje të tjera:
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);

Më lejoni t'ju kujtoj gjithashtu se sipas statistikave të mbledhura, ju mund të merrni pyetjet më të vështira:
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

Ju gjithashtu mund të shkruani për MySQL. Për ta bërë këtë, ju duhet të instaloni mysql-connector-net dhe pastaj shkruani diçka si kjo:
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;

Result

Ky artikull ka mbuluar një shembull të numëruesve të performancës (artikujve) në Zabbix. Kjo qasje ju lejon të njoftoni administratorët për probleme të ndryshme në kohë reale ose pas një kohe të caktuar. Kështu, kjo qasje lejon minimizimin e shfaqjes së një problemi kritik në të ardhmen dhe ndalimin e funksionimit të DBMS dhe serverit, i cili nga ana tjetër mbron prodhimin nga ndalimi i proceseve të punës.
Artikulli i mëparshëm: Puna rutinë me bazën e të dhënave të sistemit të informacionit 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 motorin e bazës së të dhënave të serverit SQL
» SQL Lifestyle
» Aftësitë SQLS
» TechNet Microsoft
» Analizimi i përdorimit të kujtesës
» Analiza e Performancës
» Dokumentacioni SQL
» Shënimet e Windows

Burimi: www.habr.com

Shto një koment