Forord
Der opstår ofte behov for at informere administratoren om problemer relateret til databasen i realtid.
I denne artikel vil der blive beskrevet, hvad der skal konfigureres i Zabbix for at overvåge MS SQL Server-databasen.
Jeg vil gerne bemærke, at detaljerne om, hvordan man opsætter det, ikke vil blive behandlet, men formler, generelle anbefalinger samt en detaljeret beskrivelse af, hvordan man tilføjer brugerdefinerede datavariabler via gemte procedurer, vil blive præsenteret i denne artikel.
Der vil også kun blive set på de grundlæggende ydeevne-tællere.
Løsning
Jeg vil først beskrive alle de ydeevne-tællere (via datavariabler i Zabbix), som vi har brug for:
- Logisk disk
- Avg Disc sec/Read
Viser det gennemsnitlige tidsforbrug i sekunder for at læse data fra disken. Det gennemsnitlige værdiniveau for ydeevne-tælleren Avg. Disk sec/Read bør ikke overstige 10 millisekunder. Den maksimale værdi af ydeevne-tælleren Avg. Disk sec/Read må ikke overstige 50 millisekunder.Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read], og det er også vigtigt at overvåge den specifikke disk, for eksempel sådan: perf_counter[LogicalDisk(C:)Avg. Disk sec/Read]
Eksempler på triggere:
{NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.005, niveau-høj
og
{NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.0025, niveau-mellem - Avg Disc sec/Write
Viser det gennemsnitlige tidsforbrug i sekunder for at skrive data til disken. Det gennemsnitlige værdiniveau for ydeevne-tælleren Avg. Disk sec/Write bør ikke overstige 10 millisekunder. Den maksimale værdi af ydeevne-tælleren Avg. Disk sec/Write må ikke overstige 50 millisekunder.Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write], og det er også vigtigt at overvåge den specifikke disk, for eksempel sådan: perf_counter[LogicalDisk(C:)Avg. Disk sec/Write]
Eksempler på triggere:
{NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.005, niveau-høj
og
{NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.0025, niveau-mellem - Avg Disk Queue Length
Den gennemsnitlige længde af diskforespørgsler. Viser antallet af forespørgsler til disken, der venter på behandling inden for et bestemt tidsinterval. En kø på højst 2 for en enkelt disk betragtes som normal. Hvis der er mere end to forespørgsler i køen, er det muligt, at disken er overbelastet og ikke kan håndtere de indkommende forespørgsler. For at præcisere, hvilke specifikke operationer disken har problemer med, kan man bruge tællerne Avg. Disk Read Queue Length (forespørgsler til læsning) og Avg. Disk Write Queue Length (forespørgsler til skrivning).
Værdien af Avg. Disk Queue Length måles ikke, men beregnes ifølge Littles lov fra den matematiske teori om køer. Ifølge denne lov svarer antallet af forespørgsler, der venter på behandling, i gennemsnit til frekvensen af indkomne forespørgsler ganget med behandlingstiden for en forespørgsel. Det vil sige, i vores tilfælde er Avg. Disk Queue Length = (Disk Transfers/sec) * (Avg. Disk sec/Transfer).Avg. Disk Queue Length præsenteres som en af de vigtigste tællere til at bestemme belastningen på disksystemet, men for en passende vurdering er det nødvendigt at have et præcist billede af den fysiske struktur i lagringssystemet. For eksempel er en værdi over 2 kritisk for en enkelt harddisk, mens man skal være bekymret ved en værdi over 4 * 2 = 8, hvis disken er placeret i et RAID-array med 4 diske.
Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk Queue Length], og det er også vigtigt at holde øje med den specifikke disk, for eksempel: perf_counter[LogicalDisk(C:)Avg. Disk Queue Length]
- Avg Disc sec/Read
- Hukommelse
- Sider/sec
Viser antallet af sider, som SQL Server har læst fra disk eller skrevet til disk for at muliggøre adgang til hukommelsessider, der ikke var indlæst i RAM på tidspunktet for anmodningen. Denne værdi er summen af værdierne Pages Input/sec og Pages Output/sec, og den tager også højde for sidekapsling (paging/swap) af systemcache-hukommelse til adgang til applikationsdatafiler. Desuden omfatter den også swap af ikke-cacherede filer, der vises direkte i hukommelsen. Dette er den primære tæller, man skal overvåge, hvis der observeres en stor belastning på hukommelsesbrugen og den deraf følgende overdrevne sidekapsling. Denne tæller karakteriserer niveauet af swap, og dens normale (ikke-spids) værdi bør være tæt på nul. Øget swap indikerer behov for at opgradere RAM eller reducere antallet af kørende applikationer på serveren.Zabbix: perf_counter[MemoryPages/sec]
Eksempel på trigger:
{NODE_NAME:perf_counter[MemoryPages/sec].min(5m)}>1000, niveau-information - Page Faults/sec
Denne værdi er tælleren for sidefejl. En sidefejl opstår, når en proces refererer til en side af virtuel hukommelse, som ikke er i det aktive hukommelsessæt. Denne tæller tager højde for både de sidefejl, der kræver adgang til disk, og dem, der forårsages af at siden ikke er i det arbejdsrelaterede sæt i RAM. De fleste CPU'er kan håndtere sidefejl af den anden type uden større forsinkelser. Dog kan behandling af sidefejl af den første type, der kræver diskadgang, føre til betydelige forsinkelser.
Zabbix: perf_counter[MemoryPage Faults/sec]
Eksempel på trigger:
{NODE_NAME:perf_counter[MemoryPage Faults/sec].min(5m)}>1000, niveau-information - Tilgængelige bytes
Sporing af mængden af tilgængelig hukommelse i bytes til udførelse af forskellige processer. Lave tal indikerer hukommelsesmangel. Løsningen er at øge hukommelsen. Denne tæller bør i de fleste tilfælde konstant være over 5000 KB.
Det giver mening at manuelt indstille en grænse for Available Mbytes af følgende årsager:•50% af den frie hukommelse er tilgængelig = Fremragende
•25% af den tilgængelige hukommelse = Kræver opmærksomhed
•10% er ledig = Mulige problemer
•Mindre end 5% tilgængelig hukommelse = Kritisk for hastigheden, intervention nødvendig.
Zabbix: perf_counter[MemoryAvailable Bytes]
- Sider/sec
- Processor (Total): % Processor Time
Denne tæller viser procentdelen af tiden, hvor processoren har været optaget med at udføre operationer for ikke-inaktive tråde (non-Idle thread). Denne værdi kan betragtes som en andel af tiden, der bruges til at udføre nyttigt arbejde. Hver processor kan tildeles en inaktiv tråd, der bruger unødvendige processorcykler, som ikke bruges af andre tråde. For denne tæller er der karakteristiske kortvarige toppe, som kan nå op på 100 procent. Men hvis der observeres længere perioder, hvor processorudnyttelsen er over 80 procent, vil systemet være mere effektivt med flere processorer.Zabbix: perf_counter[Processor(_Total)% Processor Time], her kan der også være uddata pr. kerner
Eksempel på trigger:
{NODE_NAME:perf_counter[Processor(_Total)% Processor Time].min(5m)}>80, niveau-informations - Netværksinterface (*): % Bytes Total/sec
Det samlede antal overførte og modtagne bytes pr. sekund over alle interfaces. Dette er båndbredden for interface (i bytes). Det er nødvendigt at sammenligne denne tæller med den maksimale båndbredde for netværkskortet. Generelt bør denne tæller ikke vise mere end 50% udnyttelse af netværksadapterens båndbredde.
Zabbix: perf_counter[Network Interface(*)Bytes Sent/sec] - MS SQL Server: Access Methods
Objektet Access Methods i SQL Server leverer tællere, der hjælper med at overvåge adgangen til logiske data i databasen. Den fysiske adgang til databasens sider på disken kontrolleres af tællere fra buffer manageren. At overvåge dataadgangsmetoderne i databasen hjælper med at bestemme, om ydeevnen for forespørgsler kan forbedres ved at tilføje eller ændre indekser, tilføje eller flytte sektioner, tilføje filer eller filgrupper, defragmentere indekser eller ændre forespørgsels teksten. Derudover kan tællere fra objektet Access Methods overvåge størrelsen af data, indekser og ledig plads i databasen, hvilket kontrollerer volumen og fragmentering for hver serverinstans. Overdreven fragmentering af indekser kan betydeligt sænke ydeevnen.- Side Splitter/sec
Antallet af sideopdelinger pr. sekund, der udføres som følge af sideoverskridelser i indekset. En høj værdi for denne måling indikerer, at SQL Server skal udføre mange ressourcekrævende opgaver ved opdeling af sider og flytning af dele af eksisterende sider til nye placeringer under indsættelse og opdatering af data. Sådanne operationer bør undgås, hvis det er muligt. Problemet kan forsøges løst på to måder:
— oprette et klyngeindeks for kolonner med automatisk inkrementering. I dette tilfælde vil nye poster ikke blive placeret inden i sider, der allerede er optaget af data, men i stedet optage nye sider sekventielt;
— ombygge indeksene og øge værdien af parameteren Fillfactor. Denne parameter gør det muligt at reservere plads i indeks siderne til nye data uden at skulle udføre sideopdelingsoperationer.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:Access MethodsPage Splits/sec»,30]
Eksempel på trigger: {NODE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:Access MethodsPage Splits/sec»,30].last()}>{NODE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:SQL StatisticsBatch Requests/sec»,30].last()}\/5, niveau-info - Full Scans\/sek
Antallet af ubegrænsede fuldskanninger pr. sekund. Disse operationer inkluderer scanning af hovedtabellen og fuld indeksscanning. En stabil stigning i denne måling kan indikere systemdegradering (mangel på nødvendige indekser, stærk fragmentering af dem, at optimereren ikke bruger eksisterende indekser, tilstedeværelsen af ubrugte indekser). Det skal dog bemærkes, at fuld scanning af små tabeller ikke altid er dårligt, da det kan være hurtigere at foretage en fuld scanning, hvis hele tabellen kan placeres i RAM. Men i de fleste tilfælde vil en stabil stigning i denne tæller indikere systemdegradering. Alt dette gælder kun for OLTP-systemer. I OLAP-systemer er vedvarende fuld skanninger normale.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:Access MethodsFull Scans\/sek»,30]
- Side Splitter/sec
- MS SQL Server: Buffer Manager
Buffer Manager-objektet giver tællere, der gør det muligt at overvåge, hvordan SQL Server bruger følgende ressourcer:
— hukommelse til opbevaring af datablade;
– tællere, der bruges til at overvåge fysisk input/output, når SQL Server læser og skriver databaser;
– udvidelse af bufferpuljen for at øge buffer-cachen ved hjælp af hurtig, ikke-flygtig hukommelse, såsom solid-state-drev (SSD);
– overvågning af hukommelse og tællere, der bruges af SQL Server, hjælper med at indhente følgende oplysninger;
– eksisterer der "flaskehalse" forårsaget af utilstrækkelig fysisk hukommelse. Hvis ofte anvendte data ikke kan opbevares i cachen, bliver SQL Server nødt til at læse dem fra disken;
– kan effektiviteten af forespørgsler forbedres ved at øge mængden af hukommelse eller allokere ekstra hukommelse til caching af data eller opbevaring af interne strukturer i SQL Server;
– hvor ofte SQL Server læser data fra disken. I sammenligning med andre operationer, såsom adgang til hukommelse, tager fysisk input/output længere tid. At reducere input/output kan forbedre forespørgselsudførelsens ydeevne.- Buffer Cache hit ratio
Viser, hvor godt SQL Server kan placere data i buffer-cachen. Jo højere denne værdi er, jo bedre, da for effektiv adgang fra SQL Server til datasiderne, skal de være i buffer-cachen, og operationer med fysisk input/output (I/O) bør være fraværende. Hvis der observeres et vedvarende fald i det gennemsnitlige værdiniveau for denne tæller, skal der overvejes at tilføje RAM. Denne værdi skal altid være over 90% for OLTP-systemer og over 50% for OLAP-systemer.
Zabbix: perf_counter["MSSQL$INSTANS_NAVN:Buffer ManagerBuffer cache hit ratio",30]
Eksempler på triggere: {NODE_NAVN:perf_counter["MSSQL$INSTANS_NAVN:Buffer ManagerBuffer cache hit ratio",30].last()}<70, niveau-højt
og
{NODE_NAVN:perf_counter["MSSQL$INSTANS_NAVN:Buffer ManagerBuffer cache hit ratio",30].last()}<80, niveau-moderat - Page life expectancy
Viser, hvor længe en side vil forblive i hukommelse i sin nuværende tilstand. Hvis værdien konstant falder, betyder det, at systemet misbruger bufferpuljen. Dette kan potentielt medføre problemer med hukommelsesdriften, hvilket resulterer i nedsat ydeevne. Det skal bemærkes, at der ikke findes en universel tærskel, under hvilken man entydigt kan konkludere, at systemet misbruger bufferpuljen (tærsklen på 300 sekunder er forældet siden MS SQL Server 2012).
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:Buffer ManagerPage life expectancy»,30]
Eksempel på trigger: {INSTANCE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:Buffer ManagerPage life expectancy»,30].last()}<5, niveau-information
- Buffer Cache hit ratio
- MS SQL Server: Generel statistik
Objektet General Statistics (Generel statistik) i SQL Server giver tællere, der gør det muligt at overvåge serverens samlede aktivitet, såsom antallet af samtidige forbindelser og antallet af brugere per sekund, der tilslutter sig eller afbryder forbindelsen fra den computer, hvor forekomsten af SQL Server kører. Disse målinger er nyttige i store online transaktionsbehandlingssystemer (OLTP), hvor mange klienter konstant forbinder og afbryder forbindelsen til SQL Server-forekomsten.- Proces blokeret
Antallet af blokerede processer i øjeblikket.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:General StatisticsProcesses blocked»,30]
Eksempel på trigger: ({INSTANCE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:General StatisticsProcesses blocked»,30].min(2m,0)}>=0)
og ({INSTANCE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:General StatisticsProcesses blocked»,30].time(0)}>=50000)
og ({INSTANCE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:General StatisticsProcesses blocked»,30].time(0)}<=230000), niveau-information (her gælder alarmbegrænsningen fra kl. 05:00 til 23:00) - Brugerforbindelser
Antallet af brugere, der i øjeblikket er tilsluttet SQL Server.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:General StatisticsUser Connections»,30]
- Proces blokeret
- MS SQL Server: Låse
Objektet Locks (Låse) i Microsoft SQL Server giver oplysninger om SQL Server-låse, der er opnået for forskellige typer ressourcer. Låse gives på ressourcer i SQL Server, såsom læste eller ændrede rækker af transaktioner, for at forhindre samtidig brug af ressourcer af flere transaktioner. For eksempel, hvis en eksklusiv (X) lås er opnået af en transaktion på en række i en tabel, vil ingen anden transaktion kunne ændre denne række, indtil låsen er frigivet. Minimisering af brugen af låse øger parallelismen, hvilket kan forbedre den samlede ydeevne. Flere forekomster af objektet Locks kan spores samtidig, hver repræsenterer en lås af en bestemt typen ressource.- Gennemsnitlig ventetid (ms)
Den gennemsnitlige ventetid (i millisekunder) for alle låseanmodninger, hvor der var behov for at vente. Denne tæller viser, hvor lang tid brugernes processer i gennemsnit skal tilbringe i kø for at få låse på ressourcen. Den maksimalt acceptable værdi for denne tæller afhænger helt af din opgave; det kan være svært at bestemme et gennemsnitligt niveau for alle applikationer her. En alt for høj værdi for denne tæller kan indikere problemer med låsene i din database.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:Locks(_Total)Gennemsnitlig ventetid (ms)»,30]
Eksempel på trigger: {NODE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:Locks(_Total)Gennemsnitlig ventetid (ms)»,30].last()}>=500, niveau-informasjon - Låseventetid (ms)
Den samlede ventetid for låse (i millisekunder) i det sidste sekund.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:Locks(_Total)Låseventetid (ms)»,30] - Låseventet / sek.
Antallet af tilfælde i det sidste sekund, hvor en tråd måtte vente på grund af en låseanmodning.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:Locks(_Total)Låseventet / sek.»,30] - Låsetidsoverskridelser / sek.
Antallet af gange, hvor det ikke lykkes at få en lås ved at spinne. Værdien af SQL Server konfigurationens spin-counter bestemmer antallet af 'spins' en tråd skal gøre, før tiden går ud og tråden går i inaktiv tilstand.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:Locks(_Total)Låsetidsoverskridelser / sek.»,30]
Eksempel på trigger: {NODE_NAME:perf_counter[«MSSQL$INSTANCE_NAME:Locks(_Total)Locks(_Total)Låsetidsoverskridelser / sek.»,30].last()}>1000, niveau-informasjon - Låseanmodninger / sek.
Antallet af forespørgsler pr. sekund af den angivne låsetype.
Zabbix: perf_counter[«MSSQL$INSTANS_NAVN:Locks(_Total)Lock Requests/sec»,30]
Eksempel på trigger: {NODE_NAVN:perf_counter[«MSSQL$INSTANS_NAVN:Locks(_Total)Lock Requests/sec»,30].last()}>500000, niveau-informativ - Låse Antal af dødlåse pr. sek.
Antallet af låseforespørgsler pr. sekund, der resulterer i dødlåse. Dødlåse indikerer forkert konstruerede forespørgsler, der blokerer delte ressourcer.
Zabbix: perf_counter[«MSSQL$INSTANS_NAVN:Number of Deadlocks/sec»,30]
Eksempel på trigger: {NODE_NAVN:perf_counter[«MSSQL$INSTANS_NAVN:Locks(_Total)Number of Deadlocks/sec»,30].last()}>1, niveau-høj
- Gennemsnitlig ventetid (ms)
- MS SQL Server: Hukommelsesstyrer
Objektet Hukommelsesstyrer i Microsoft SQL Server leverer Zælere til overvågning af serverens samlede hukommelsesforbrug. Overvågning af serverens hukommelsesforbrug for at evaluere brugerhandlinger og ressourceforbrug kan hjælpe med at identificere ydeevnedefekter. Kontrollere den hukommelse, der benyttes af SQL Server instansen, kan hjælpe med at bestemme:
— om der er mangler på utilstrækkelig fysisk hukommelse til at gemme ofte anvendte data i cachen. Hvis hukommelsen er utilstrækkelig, skal SQL Server hente data fra disken;
— om forespørgselsydelsen kan forbedres ved at tilføje mere hukommelse eller øge mængden af tilgjengelig hukommelse til caching af data eller interne strukturer i SQL Server.- Hukommelsestildelinger I Hævet
Indikerer det samlede antal processer, der har fået tildelt arbejdsområdets hukommelse. Hvis denne indikator stabilt falder, bør RAM'en øges.
Zabbix: perf_counter[«MSSQL$INSTANS_NAVN:Memory ManagerMemory Grants Outstanding»,30] - Hukommelsestildelinger I Ventetilstand
Indikerer det samlede antal processer, der venter på tildeling af arbejdssteder. Hvis denne indikator stabilt stiger, bør RAM'en øges.
Zabbix: perf_counter[«MSSQL$INSTANS_NAVN:Memory ManagerMemory Grants Pending»,30]
- Hukommelsestildelinger I Hævet
- MS SQL Server: Statistikker
Objektet Statistikker i Microsoft SQL Server giver funktionalitet til overvågning af antallet af kompileringer og typer af forespørgsler, der sendes til SQL Server instansen. Overvågning af antallet af kompileringer og genkompileringer af forespørgsler samt antallet af pakker modtaget af SQL Server instansen giver indsigt i, hvor hurtigt SQL Server udfører brugerforespørgsler, og hvor effektivt forespørgselsoptimereren behandler dem.- Batch Requests/sec
Antallet af Transact-SQL kommando pakker modtaget per sekund. Denne statistik påvirkes af eventuelle begrænsninger (input-output, antal brugere, cache størrelse, forespørgslernes kompleksitet osv.). Et højt antal pakkeforespørgsler indikerer høj båndbredde.
Zabbix: perf_counter[«MSSQL$INSTANCE_NAME:SQL StatisticsBatch Requests/sec»,30]
- Batch Requests/sec
Derudover kan du også konfigurere andre datakilder (og oprette triggers baseret på dem med efterfølgende notifikation). For eksempel:
1) størrelsen på ledig diskplads
2) størrelserne på DB-datafiler og logfiler
osv.
Dog viser alle disse målinger ikke problemer med forespørgsler i realtid.
For dette er det nødvendigt at oprette dine egne specielle tællere.
Af fortrolighedsmæssige årsager vil jeg ikke give eksempler på sådanne tællere. Især da de konfigureres unikt for hvert system. Men jeg vil bemærke, at for systemer som 1C, NAV og CRM kan der oprettes specialiserede tællere i samarbejde med de relevante udviklere.
Jeg vil give et eksempel på oprettelsen af en generel måling, der viser, hvor mange forespørgsler der udføres, og hvor mange forespørgsler der venter på udførelse (suspendere eller blokere) på et givent tidspunkt.
For dette er det nødvendigt at oprette en gemt procedure:
Kode
USE [DATABASE_NAME]
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
Derefter skal du gå ind i mappen, hvor Zabbix (zabbixconfuserparams.d) er placeret, og oprette 2 filer med filtypen .ps1 (PowerShell) og skrive følgende kode i hver af dem:
Kode til udførende forespørgsler
$SQLServer = "INSTANCE_NAME";
$uid = "LOGIN";
$pwd = "PASSWORD";
$Status="running";
$connectionString = "Server = $SQLServer; Database=DATABASE_NAME; Integrated Security = False; User ID = $uid; Password = $pwd;";
$connection = New-Object System.Data.SqlClient.SqlConnection;
$connection.ConnectionString = $connectionString;
# Opretter en forespørgsel direkte til 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;
Kode til ventende forespørgsler
$SQLServer = "INSTANCE_NAME";
$uid = "LOGIN";
$pwd = "PASSWORD";
$Status="suspended";
$connectionString = "Server = $SQLServer; Database=DATABASE_NAME; Integrated Security = False; User ID = $uid; Password = $pwd;";
$connection = New-Object System.Data.SqlClient.SqlConnection;
$connection.ConnectionString = $connectionString;
# Opretter en forespørgsel direkte til 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;
Dernæst skal du oprette en fil med brugerparametre og en .conf-udvidelse (eller tilføje linjer til en eksisterende brugerfil, hvis den er blevet oprettet tidligere) og indsætte følgende linjer:
UserParameter=PARAMETER_NAME_COUNT_EXECUTED_REQUESTS,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILENAME_FOR_EXECUTED_REQUESTS.ps1
UserParameter=PARAMETER_NAME_COUNT_PENDING_REQUESTS,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILENAME_FOR_PENDING_REQUESTS.ps1
Herefter gemmer vi .conf-filen og genstarter Zabbix-agenten.
Herefter tilføjer vi to nye elementer i Zabbix (i dette tilfælde er navnene og nøglerne de samme):
PARAMETER_NAME_COUNT_EXECUTED_REQUESTS
PARAMETER_NAME_COUNT_PENDING_REQUESTS
Nu kan vi oprette grafer og triggere for de oprettede brugerdataelementer.
Hvis antallet af ventende forespørgsler pludselig stiger, kan den næste forespørgsel vise alle udførende og ventende forespørgsler i øjeblikket med detaljer om, hvor og med hvilken login forespørgslen udføres, teksten og forespørgselsplanen samt andre detaljer:
Kode
/*Активные, готовые к выполнению и ожидающие запросы, а также те, что явно блокируют другие сеансы*/
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);
Jeg minder også om, at man kan få de mest belastende forespørgsler baseret på de indsamlede statistikker:
Kode
/*
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
Det kan også skrives til MySQL. For dette skal man installere og derefter skrive noget lignende denne kode:
Kode til ventende forespørgsler
#Задаем переменные для подключение к 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;
Resultat
I denne artikel blev der set på et eksempel på ydeevne tællere (dataelementer) i Zabbix. Denne tilgang muliggør, at administratorer underrettes om forskellige problemer i realtid eller efter et bestemt tidsrum. På denne måde hjælper denne tilgang med at minimere risikoen for kritiske problemer og nedbrud af DBMS og serveren, hvilket i sidste ende beskytter produktionen mod nedetid i arbejdsprocesserne.
The previous article:
Kilder:
»
»
»
»
»
»
»
»
»
»
Kilde: habr.com
