Предговор
Често възниква необходимост от реално време да се информира администратора за проблеми, свързани с базата данни (БД).
В тази статия ще бъде описано какво е необходимо да се настрои в Zabbix за наблюдение на базата данни MS SQL Server.
Обърнете внимание, че подробно как да се настрои няма да бъде предоставено, но формули и общи препоръки, както и подробно описание за добавяне на потребителски елементи данни чрез храними процедури ще бъдат предоставени в тази статия.
Тук ще бъдат разгледани само основните счетчици на производителността.
Решение
Първо ще опиша всички нужни счетчици на производителността (чрез елементи данни в Zabbix):
- Логичен диск
- Avg Disc sec/Read
Показва изразеното в секунди средно време за четене на данни от диска. Средното значение на счетчика на производителността Avg. Disk sec/Read не трябва да надвишава 10 милисекунди. Максималното значение на счетчика на производителността Avg. Disk sec/Read не трябва да надвишава 50 милисекунди.Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read], а също е важно да се следи за нужния диск, например така: perf_counter[LogicalDisk(C:)Avg. Disk sec/Read]
Примери на тригери:
{ИМЕ_НА_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.005, ниво-високо
и
{ИМЕ_НА_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.0025, ниво-средно - Avg Disc sec/Write
Показва изразеното в секунди средно време за запис на данни на диска. Средното значение на счетчика на производителността Avg. Disk sec/Write не трябва да надвишава 10 милисекунди. Максималното значение на счетчика на производителността Avg. Disk sec/Write не трябва да надвишава 50 милисекунди.Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write], а също е важно да се следи за нужния диск, например така: perf_counter[LogicalDisk(C:)Avg. Disk sec/Write]
Примери на тригери:
{ИМЕ_НА_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.005, ниво-високо
и
{ИМЕ_НА_УЗЛА:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.0025, ниво-средно - Avg Disk Queue Length
Средната дължина на опашката на заявките за диск. Показва броя на заявките за диск, които чакат обработка в течение на определен интервал от време. Нормално е опашката да не надвишава 2 за единичен диск. Ако в опашката има повече от две заявки, дискът може да е претоварен и не успява да обработва входящите заявки. Можете да уточните с кои точно операции дискът не се справя, като използвате счетчиците Avg. Disk Read Queue Length (опашка на заявките за четене) и Avg. Disk Write Queue Length (опашка на заявките за запис).
Стойността на Avg. Disk Queue Length не се измерва, а се изчислява по закона на Литъл от математическата теория на опашките. Според този закон, броят на заявките, чакащи обработка, средно е равен на честотата на постъпване на заявките, умножена по времето за обработка на заявка. Т.е. в нашия случай Avg. Disk Queue Length = (Disk Transfers/sec) * (Avg. Disk sec/Transfer).Avg. Disk Queue Length е изведен като един от основните счетчици за определяне на натоварването на дисковата подсистема, но за адекватна оценка е необходимо точно да се представя физичната структура на системата за съхранение. Например, за единичен твърд диск критично е стойността да бъде над 2, а ако дискът е част от RAID масив от 4 диска, то е нужно да се притеснявате, ако стойността надвишава 4*2=8.
Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk Queue Length], а също така е важно да се следи за нужния диск, например така: perf_counter[LogicalDisk(C:)Avg. Disk Queue Length]
- Avg Disc sec/Read
- Памет
- Pages/sec
Показва броя на страниците, които SQL Server е чел от диска или е записал на диска, за да разреши достъпа до страниците в паметта, които не са били заредени в оперативната памет в момента на достъпа. Тази стойност е сумата на стойностите Pages Input/sec и Pages Output/sec и включва страничен обмен (подкачка/свопинг) на системната кеш памет за достъп до файловете на приложението. Освен това включва подкачка на некеширани файлове, директно отразени в паметта. Това е основният счетчик, за който трябва да се следи, ако има голямо натоварване на използването на памет и свързания с него излишен страничен обмен. Този счетчик характеризира обема на свопинга и неговата нормална (не пиково) стойност трябва да бъде близка до нула. Увеличението на свопинга показва необходимост от увеличаване на RAM или намаляване на броя на изпълняващите се приложения на сървера.Zabbix: perf_counter[MemoryPages/sec]
Пример за тригер:
{ИМЕ_НА_ВЪЗЛА:perf_counter[MemoryPages/sec].min(5m)}>1000, ниво-информация - Page Faults/sec
Тази стойност е измервател на грешките на страниците. Грешка на страницата възниква, когато процес се отнася до страница на виртуалната памет, която не е в работния набор на оперативната памет. Този счетчик отчита както грешките на страниците, които изискват достъп до диска, така и тези, които са причинени от присъствието на страницата извън работния набор в оперативната памет. Повечето процесори могат да обработват грешките на страниците от втория тип без значителни закъснения. Обработката на грешките на страниците от първия тип, изискваща достъп до диска, може да доведе до значителни закъснения.
Zabbix: perf_counter[MemoryPage Faults/sec]
Пример за тригер:
{ИМЕ_НА_ВЪЗЛА:perf_counter[MemoryPage Faults/sec].min(5m)}>1000, ниво-информация - Достъпни Байтове
Проследява количеството налична памет в байтове за изпълнение на различни процеси. Ниските показатели означават недостиг на памет. Решението е да се увеличи паметта. Този счетчик в повечето случаи трябва да бъде постоянно над 5000 КВ.
Има смисъл да се зададе праг за Available Mbytes ръчно от съображения:•50% свободна памет на разположение = Отлично
•25% налична памет = Изисква внимание
•10% свободно = Могат да възникнат проблеми
•По-малко от 5% налична памет = Критично за скоростта, необходимо е вмешателство.
Zabbix: perf_counter[MemoryAvailable Bytes]
- Pages/sec
- Процесор (Общо): % Време на Процесора
Този брояч показва процентното отношение на времето, през което процесорът е бил зает с изпълнението на операции за непразни нишки (non-Idle thread). Тази стойност може да се разглежда като дял от времето, което се пада на изпълнението на полезна работа. Всеки процесор може да бъде назначен на празна нишка, която консумира непродуктивни цикли на процесора, не използвани от другите нишки. За този брояч са характерни краткотрайни върхове, които могат да достигнат 100 процента. Въпреки това, ако се наблюдават продължителни периоди, в които използването на процесора е над 80 процента, системата ще бъде по-ефективна при използването на повече процесори.Zabbix: perf_counter[Processor(_Total)% Processor Time], тук също може да се показва по ядра
Пример за тригер:
{НАЗВАНИЕ_УЗЛА:perf_counter[Processor(_Total)% Processor Time].min(5m)}>80, ниво-информация - Мрежов интерфейс (*): % Bytes Total/sec
Общото количество предадени и получени байтове на секунда през всички интерфейси. Това е пропускателната способност на интерфейса (в байтове). Необходимо е да се сравни стойността на този брояч с максималната пропускателна способност на мрежовата карта. Обикновено, този брояч не трябва да показва повече от 50% използване на пропускателната способност на мрежовия адаптер.
Zabbix: perf_counter[Network Interface(*)Bytes Sent/sec] - MS SQL Server: Методи за достъп
Обектът Методи за достъп (Access Methods) в SQL Server предоставя броячи, които помагат да се следи достъпът до логични данни в рамките на базата данни. Физическият достъп до страниците на базата данни на диска се контролира с помощта на броячи на буферния диспетчер. Наблюдението на методите за достъп до данни в базата данни помага да се определи дали може да се увеличи производителността на запитванията чрез добавяне или промяна на индекси, добавяне или преместване на секции, добавяне на файлове или групи от файлове, дефрагментиране на индекси или промяна на текста на запитванията. Освен това, с помощта на броячите на обекта Методи за достъп, може да се следи размерът на данните, индексите и свободното пространство в базата данни, контролирайки обема и фрагментацията за всеки екземпляр на сървъра. Прекомерната фрагментация на индексите може значително да намали производителността.- Page Splits/sec
Броят на разделенията на страниците за секунда, извършвани в резултат на препълването на индекса. Високата стойност на този показател означава, че при извършване на операции по вмъкване и промяна на данни SQL Server трябва да извърши много ресурсоемки операции по разделяне на страници и преместване на част от съществуващата страница на ново място. Тези операции трябва да се избягват, когато е възможно. Проблемът може да се опита да се реши по два начина:
— да се създаде клъстерен индекс за колони с автоматично увеличаване. В този случай новите записи няма да бъдат поставяни в страници, вече заети с данни, а ще заемат последователно нови страници;
— да се преизграят индексите, увеличавайки стойността на параметъра Fillfactor. Този параметър позволява да се резервира свободно място в страниците на индексите, което ще се използва за разполагане на нови данни, без необходимост от операции по разделяне на страници.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Access MethodsPage Splits/sec»,30]
Пример за тригер: {ИМЕ_НА_ВЪЗЛА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Access MethodsPage Splits/sec»,30].last()}>{ИМЕ_НА_ВЪЗЛА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:SQL StatisticsBatch Requests/sec»,30].last()}\/5, ниво-информация - Full Scans/sec
Броят на неограничените операции по пълно сканиране за секунда. Към тези операции спадат сканирането на основната таблица и пълното сканиране на индекса. Постоянното увеличаване на този показател може да сигнализира за деградация на системата (липса на необходимите индекси, тяхната силна фрагментация, неупотребата на съществуващите индекси от оптимизатора, наличието на неизползвани индекси). Въпреки това, е важно да се отбележи, че пълното сканиране на малки таблици не винаги е негативно, тъй като ако успеем да поставим цялата таблица в ОЗУ, пълното сканиране ще бъде по-бързо. Но в повечето случаи стабилният ръст на показателя на този брояч ще говори за деградация на системата. Всичко това се отнася само за OLTP-системи. В OLAP-системите постоянните пълни сканирания са нормални.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Access MethodsFull Scans/sec»,30]
- Page Splits/sec
- MS SQL Server: Buffer Manager
Обектът Buffer Manager (мениджър на буфера) предоставя броячи, позволяващи да се наблюдава как SQL Server използва следните ресурси:
— памет за съхранение на страници с данни;
— броячи, които служат за мониторинг на физическия вход/изход, когато SQL Server чете и записва страници от бази данни;
— разширение на буферния пул за увеличаване на буферния кеш с помощта на бърза енергонезависима памет, например SSD;
— мониторинг на паметта и броячите, използвани от SQL Server, помага за получаване на следната информация;
— съществуват ли "тесни места", причинени от недостиг на физическа памет. Ако често използваните данни не могат да бъдат запазени в кеша, SQL Server е принуден да ги чете от диска;
— може ли да се повиши ефективността при изпълнение на запитвания, като се увеличи обемът на паметта или се предостави допълнителна памет за кеширане на данни или съхранение на вътрешни структури на SQL Server;
— колко често SQL Server чете данни от диска. В сравнение с другите операции, като достъп до паметта, физическият вход-изход отнема повече време. Намаляването на обема на вход-изхода може да повиши производителността на изпълнението на запитвания.- Според показателя за успех на кеша
Показва доколко SQL Server може да разположи данните в буфера на кеша. Колкото по-висока е тази стойност, толкова по-добре, тъй като за ефективен достъп на SQL сървъра до страниците данни, те трябва да се намират в буфера на кеша и операциите на физическия вход-изход (I/O) трябва да отсъстват. Ако наблюдавате постоянен спад на средната стойност на този брояч, е необходимо да се обмисли добавяне на RAM. Този показател винаги трябва да бъде над 90% за OLTP системи и над 50% за OLAP системи.
Zabbix: perf_counter["MSSQL$ИМЕ_ЕКЗЕМПЛЯРА:Buffer ManagerBuffer cache hit ratio",30]
Примери на тригери: {ИМЕ_ВЪЗЛА:perf_counter["MSSQL$ИМЕ_ЕКЗЕМПЛЯРА:Buffer ManagerBuffer cache hit ratio",30].last()}<70, ниво-високо
и
{ИМЕ_ВЪЗЛА:perf_counter["MSSQL$ИМЕ_ЕКЗЕМПЛЯРА:Buffer ManagerBuffer cache hit ratio",30].last()}<80, ниво-средно - Очаквано време на живот на страница
Показва колко дълго страница ще остане в паметта в текущото си състояние. Ако стойността постоянно намалява, това означава, че системата злоупотребява с буферния пул. Следователно, потенциалната работа на паметта може да предизвика проблеми, водещи до намаляване на производителността. Струва си да се отбележи, че няма универсален показател, под който да се съди недвусмислено, че системата злоупотребява с буферния пул (показателят от 300 секунди е остарял с MS SQL Server 2012).
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Buffer ManagerPage life expectancy»,30]
Пример за тригер: {ИМЕ_НА_ВРЪЗКАТА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Buffer ManagerPage life expectancy»,30].last()}<5, ниво-информация
- Според показателя за успех на кеша
- MS SQL Server: Общи статистики
Обектът General Statistics (Общи статистики) в SQL Server предоставя счетчици, които позволяват наблюдение на общата активност на сървъра, например, броя на паралелните връзки и броя на потребителите на секунда, които се свързват или отключват от компютъра, на който е стартиран екземпляра на SQL Server. Тези показатели са полезни в големи системи за оперативна обработка на транзакции (OLTP), където много клиенти постоянно се свързват и отключват от екземпляра на SQL Server.- Процес блокиран
Брой на в момента блокираните процеси.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30]
Пример за тригер: ({ИМЕ_НА_ВРЪЗКАТА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30].min(2m,0)}>=0)
и ({ИМЕ_НА_ВРЪЗКАТА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30].time(0)}>=50000)
и ({ИМЕ_НА_ВРЪЗКАТА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:General StatisticsProcesses blocked»,30].time(0)}<=230000), ниво-информация (тук е ограничението за сигнализация от 05:00 до 23:00) - Потребителски връзки
Брой на потребителите, свързани в момента към SQL Server.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:General StatisticsUser Connections»,30]
- Процес блокиран
- MS SQL Server: Заключвания
Обект Locks (Блокировки) в Microsoft SQL Server предоставя информация за блокировките на SQL Server, получени за отделни типове ресурси. Блокировките се издават на ресурси на SQL Server, като прочетени или модифицирани редове в транзакция, с цел предотвратяване на едновременната употреба на ресурси от различни транзакции. Например, ако транзакцията получи изключителна (X) блокировка на ред в таблица, никоя друга транзакция не може да модифицира този ред, докато блокировката не бъде освободена. Минимизиране на използването на блокировки увеличава паралелизма, което може да подобри общата производителност. Могат да се проследяват няколко екземпляра на обекта Locks, всеки от които представлява блокировка на отделен вид ресурс.- Средно време на изчакване (ms)
Средното време на изчакване (в милисекунди) за всички заявки за блокировки, при които е била необходима изчакване. Този брояч показва колко средно на потребителските процеси се налага да чакат, за да наложат блокировка на ресурса. Максималната допустима стойност на този брояч напълно зависи от вашето натоварване, трудно е да се определи всякаква средна стойност за всички приложения тук. Прекалено висока стойност на този брояч може да означава проблеми с блокировките във вашата база данни.
Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЕКЗЕМПЛЯРА:Locks(_Total)Average Wait Time (ms)»,30]
Пример за тригер: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЕКЗЕМПЛЯРА:Locks(_Total)Average Wait Time (ms)»,30].last()}>=500, ниво-информация - Време на изчакване за блокировки (ms)
Общото време на изчакване за блокировки (в милисекунди) за последната секунда.
Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЕКЗЕМПЛЯРА:Locks(_Total)Lock Wait Time (ms)»,30] - Блокировъчни заявки/сек
Брой случаи през последната секунда, когато потокът е трябвало да изчака в резултат на заявка за блокировка.
Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЕКЗЕМПЛЯРА:Locks(_Total)Lock Waits/сек»,30] - Тайм-аут на блокировки/сек
Брой повторения, когато не е успял да получи блокировка чрез циклични обращения. Стойността на конфигурационния параметър на SQL Server spin counter определя броя на „оборотите“ на потока (spins), преди тайм-аутът да изтече и потокът да премине в неактивно състояние.
Zabbix: perf_counter[«MSSQL$НАЗВАНИЕ_ЕКЗЕМПЛЯРА:Locks(_Total)Lock Timeouts/сек»,30]
Пример за тригер: {НАЗВАНИЕ_УЗЛА:perf_counter[«MSSQL$НАЗВАНИЕ_ЕКЗЕМПЛЯРА:Locks(_Total)Locks(_Total)Lock Timeouts/сек»,30].last()}>1000, ниво-информация - Блокировъчни заявки/сек
Брой заявки в секунда за указания тип блокировка.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Locks(_Total)Lock Requests/sec»,30]
Пример за тригер: {ИМЕ_НА_УЗЛА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Locks(_Total)Lock Requests/sec»,30].last()}>500000, ниво-информация - Брой на мъртви блокировки в секунда
Брой на заявки за блокиране в секунда, водещи до взаимоблокировка. Наличието на взаимоблокировки показва неправилно построени заявки, които блокират общи ресурси.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Number of Deadlocks/sec»,30]
Пример за тригер: {ИМЕ_НА_УЗЛА:perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Locks(_Total)Number of Deadlocks/sec»,30].last()}>1, ниво-висок
- Средно време на изчакване (ms)
- MS SQL Server: Диспетчер на паметта
Обектът Диспетчер на паметта в Microsoft SQL Server предоставя броячи за контрол на използването на паметта на целия сървър. Контролът върху използването на паметта на целия сървър за оценка на действията на потребителите и използването на ресурси може да помогне за идентифициране на проблеми с производителността. Контролът на паметта, използван от екземпляра на SQL Server, може да помогне да се определи:
— дали съществуват недостатъци в недостатъчната физическа памет за съхранение в кеша на често използвани данни. Ако паметта не е достатъчна, SQL Server трябва да получи данни от диска;
— дали производителността на заявката може да се подобри, ако бъде добавена памет или увеличен обемът на наличната памет за кеширане на данни или вътрешни структури на SQL Server.- Outstanding Memory Grants
Указва общия брой процеси, успешно получили памет в работната област. При стабилно намаление на показателя, е необходимо да се увеличи RAM.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Memory ManagerMemory Grants Outstanding»,30] - Pending Memory Grants
Указва общия брой процеси, чакащи предоставяне на памет. При стабилен растеж на показателя, е необходимо да се увеличи RAM.
Zabbix: perf_counter[«MSSQL$ИМЕ_НА_ЕКЗЕМПЛЯРА:Memory ManagerMemory Grants Pending»,30]
- Outstanding Memory Grants
- MS SQL Server: Статистика
Обектът Статистика в Microsoft SQL Server предоставя работа на броячи за наблюдение на компилации и типове заявки, изпращани до екземпляра на SQL Server. Наблюдението на броя компилации и повторни компилации на заявки и броя пакети, получени от екземпляра на SQL Server, дава представа за това колко бързо SQL Server изпълнява заявките на потребителите и колко ефективно ги обработва оптимизаторът на заявки.- Заявки на партида в секунда
Брой пакети команди Transact-SQL, получени за секунда. На тази статистика влияят всякакви ограничения (вход-изход, количество потребители, размер на кеша, сложност на запитванията и т.н.). Високият брой запитвания пакети свидетелства за висока пропускна способност.
Zabbix: perf_counter[«MSSQL$ИМЕ_ЕКЗЕМПЛЯРА:SQL StatisticsBatch Requests/sec»,30]
- Заявки на партида в секунда
Освен всичко изброено по-горе, могат да се настроят и други елементи на данни (както и да се създадат тригери по тях за последващо уведомление). Например:
1) размер на свободното място на диска
2) размери на файловете на базата данни и на журнала
и др.
Обаче, всички тези показатели не показват проблеми точно с запитванията в реално време.
За това е необходимо да се създадат специални броячи.
Поради съображения за конфиденциалност, няма да дам примери на такива броячи. Също така, те се настройват уникално за всяка система. Но ще подчертая, че за такива системи като 1С, NAV и CRM, специализирани броячи могат да се създадат съвместно със съответните разработчици.
Ще дам пример за създаване на обобщен показател, който показва колко запитвания се изпълняват и колко запитвания очакват изпълнение (временно спряни или блокирани) в даден момент.
За това е необходимо да се създаде съхранявана процедура:
Код
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
След това необходимо е да отидете в папката, където се намира Zabbix (zabbixconfuserparams.d) и да създадете 2 файла с разширение ps1 (PowerShell) и да напишете в всеки от тях следния код:
Код за изпълняващи се запитвания
$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
$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;
Код за изчакващи запитвания
$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
$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;
Сега е необходимо да се създаде файл с потребителски параметри и разширение .conf (или да добавите редове в съществуващ такъв потребителски файл, ако той е създаден преди това) и да се вмъкнат следните редове:
UserParameter=ИМЯ_ПАРАМЕТРА_КОЛИЧЕСТВО_ИЗПЪЛНЕНИ_ЗАПИТВАНИЯ,powershell -NoProfile -ExecutionPolicy Bypass -File ПЪЛЕН_ПЪТzabbixconfuserparams.dИМЕ_ФАЙЛА_ЗА_ИЗПЪЛНЕНИ_ЗАПИТВАНИЯ.ps1
UserParameter=ИМЯ_ПАРАМЕТРА_КОЛИЧЕСТВО_ОЧАКВАЩИ_ЗАПИТВАНИЯ,powershell -NoProfile -ExecutionPolicy Bypass -File ПЪЛЕН_ПЪТzabbixconfuserparams.dИМЕ_ФАЙЛА_ЗА_ОЧАКВАЩИ_ЗАПИТВАНИЯ.ps1
След това запазете файла .conf и рестартирайте Zabbix агента.
След това добавяме два нови елемента в Zabbix (в този случай имената и ключовете съвпадат):
ИМЯ_ПАРАМЕТРА_КОЛИЧЕСТВО_ИЗПЪЛНЕНИ_ЗАПИТВАНИЯ
ИМЯ_ПАРАМЕТРА_КОЛИЧЕСТВО_ОЧАКВАЩИ_ЗАПИТВАНИЯ
Сега можем да създаваме графики и тригери за създадените потребителски елементи за данни.
Ако броят на изчакващите заявки рязко нараства, следващата заявка може да изведе всички изпълняващи се и изчакващи заявки в момента с детайли откъде и под какъв логин се изпълнява заявката, текста и плана на заявката, както и други детайли:
Код
/*Активные, готовые к выполнению и ожидающие запросы, а также те, что явно блокируют другие сеансы*/
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);
Също така напомням, че по събраната статистика може да се получат най-тежките заявки:
Код
/*
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
Може да напишете и за MySQL. За целта е необходимо да се инсталира и след това да напишете приблизително такъв код:
Код за изчакващи запитвания
#Задаем переменные для подключение к 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;
Резултат
В тази статия беше разгледан пример за броячи на производителност (елементи на данни) в Zabbix. Този подход позволява да се уведомяват администраторите за различни проблеми в реално време или след определено време. По този начин, този подход минимизира бъдещите критични проблеми и спирането на работата на СУБД и сървъра, което от своя страна защитава производството от спиране на работните процеси.
Предишната статия:
Източници:
»
»
»
»
»
»
»
»
»
»
Източник: habr.com
