Χρήση του Zabbix για την παρακολούθηση της βάσης δεδομένων του MS SQL Server

πρόλογος

Συχνά υπάρχει ανάγκη ενημέρωσης του διαχειριστή για προβλήματα που σχετίζονται με τη βάση δεδομένων (βάση δεδομένων) σε πραγματικό χρόνο.

Αυτό το άρθρο θα περιγράψει τι πρέπει να ρυθμιστεί στο Zabbix για την παρακολούθηση της βάσης δεδομένων του MS SQL Server.

Εφιστώ την προσοχή σας στο γεγονός ότι δεν θα δοθεί λεπτομερής τρόπος ρύθμισης παραμέτρων, ωστόσο, σε αυτό το άρθρο θα δοθούν τύποι και γενικές συστάσεις, καθώς και λεπτομερής περιγραφή της προσθήκης προσαρμοσμένων στοιχείων δεδομένων μέσω αποθηκευμένων διαδικασιών.
Επίσης, εδώ θα ληφθούν υπόψη μόνο οι κύριοι μετρητές απόδοσης.

Λύση

Αρχικά, θα περιγράψω όλους αυτούς τους μετρητές απόδοσης (μέσω στοιχείων στο Zabbix) που χρειαζόμαστε:

  1. Λογικός δίσκος
    1. Μέσος δίσκος δευτερολέπτων/Ανάγνωσης
      Εμφανίζει τον μέσο χρόνο σε δευτερόλεπτα για την ανάγνωση δεδομένων από το δίσκο. Η μέση τιμή του μετρητή μέσης απόδοσης. Το Disk sec/Read δεν πρέπει να υπερβαίνει τα 10 χιλιοστά του δευτερολέπτου. Η μέγιστη τιμή του μετρητή μέσης απόδοσης. Το Disk sec/Read δεν πρέπει να υπερβαίνει τα 50 χιλιοστά του δευτερολέπτου.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read], και είναι επίσης σημαντικό να παρακολουθείτε τον επιθυμητό δίσκο, για παράδειγμα: perf_counter[LogicalDisk(C:)Avg. Δευτερόλεπτο δίσκου/Ανάγνωση]

      Παραδείγματα ενεργοποίησης:
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.005, επίπεδο-υψηλό
      и
      {NOTE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Read].last()}>0.0025, level-medium

    2. Μέσος δίσκος δευτερολέπτων/Εγγραφής
      Εμφανίζει τον μέσο χρόνο σε δευτερόλεπτα για την εγγραφή δεδομένων στο δίσκο. Η μέση τιμή του μετρητή μέσης απόδοσης. Το Disk sec/Write δεν πρέπει να υπερβαίνει τα 10 χιλιοστά του δευτερολέπτου. Η μέγιστη τιμή του μετρητή μέσης απόδοσης. Το Disk sec/Write δεν πρέπει να υπερβαίνει τα 50 χιλιοστά του δευτερολέπτου.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write], και είναι επίσης σημαντικό να παρακολουθείτε τον επιθυμητό δίσκο, για παράδειγμα: perf_counter[LogicalDisk(C:)Avg. Δευτ. Δίσκος/Εγγραφή]

      Παραδείγματα ενεργοποίησης:
      {NOTE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.005, επίπεδο-υψηλό
      и
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write].last()}>0.0025, level-medium

    3. Μέσο μήκος ουράς δίσκου

      Μέσο μήκος ουράς αιτημάτων στο δίσκο. Εμφανίζει τον αριθμό των αιτημάτων δίσκου που εκκρεμούν σε επεξεργασία μέσα σε ένα καθορισμένο χρονικό διάστημα. Μια ουρά όχι μεγαλύτερη από 2 για έναν μόνο δίσκο θεωρείται φυσιολογική. Εάν υπάρχουν περισσότερες από δύο αιτήσεις στην ουρά, τότε ο δίσκος μπορεί να είναι υπερφορτωμένος και να μην μπορεί να επεξεργαστεί εισερχόμενες αιτήσεις. Μπορείτε να μάθετε ποιες ακριβώς λειτουργίες δεν μπορεί να χειριστεί ο δίσκος χρησιμοποιώντας μετρητές μέσου όρου. Μήκος ουράς ανάγνωσης δίσκου και μέσος όρος. Μήκος ουράς δίσκου Wright (ουρά αιτημάτων εγγραφής).
      Μέση τιμή Το μήκος της ουράς δίσκου δεν μετριέται, αλλά υπολογίζεται σύμφωνα με το νόμο του Little από τη μαθηματική θεωρία των ουρών. Σύμφωνα με αυτόν τον νόμο, ο αριθμός των αιτημάτων που περιμένουν να διεκπεραιωθούν, κατά μέσο όρο, ισούται με τη συχνότητα των αιτημάτων που λαμβάνονται, πολλαπλασιαζόμενη επί το χρόνο διεκπεραίωσης του αιτήματος. Εκείνοι. στην περίπτωσή μας Μέσος. Μήκος ουράς δίσκου = (Μεταφορές δίσκου/δευτ.) * (Μέσος δευτ./Μεταφορά δίσκου).

      Μέσος όρος Το μήκος ουράς δίσκου δίνεται ως ένας από τους κύριους μετρητές για τον προσδιορισμό του φορτίου στο υποσύστημα του δίσκου, ωστόσο, για να αξιολογηθεί επαρκώς, είναι απαραίτητο να αναπαρασταθεί με ακρίβεια η φυσική δομή του συστήματος αποθήκευσης. Για παράδειγμα, για έναν μεμονωμένο σκληρό δίσκο μια τιμή μεγαλύτερη από 2 θεωρείται κρίσιμη και εάν ο δίσκος βρίσκεται σε μια συστοιχία RAID 4 δίσκων, τότε θα πρέπει να ανησυχείτε εάν η τιμή είναι μεγαλύτερη από 4*2=8.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Μήκος ουράς δίσκου], και είναι επίσης σημαντικό να παρακολουθείτε τον επιθυμητό δίσκο, για παράδειγμα ως εξής: perf_counter[LogicalDisk(C:)Avg. Μήκος ουράς δίσκου]

  2. Μνήμη
    1. Σελίδες/δευτ
      Εμφανίζει τον αριθμό των σελίδων που ο SQL Server διάβασε από το δίσκο ή έγραψε στο δίσκο προκειμένου να επιλύσει τις προσβάσεις σε σελίδες μνήμης που δεν φορτώθηκαν στην κύρια μνήμη τη στιγμή της πρόσβασης. Αυτή η τιμή είναι το άθροισμα των τιμών Είσοδος/δευτερόλεπτο και Εξόδου Σελίδων/δευτ. και λαμβάνει επίσης υπόψη τη σελιδοποίηση (ανταλλαγή/ανταλλαγή) της κρυφής μνήμης του συστήματος για την πρόσβαση στα αρχεία δεδομένων της εφαρμογής. Περιλαμβάνει επίσης σελιδοποίηση μη αποθηκευμένων στην κρυφή μνήμη αρχείων απευθείας αντιστοιχισμένων με μνήμη. Αυτός είναι ο κύριος μετρητής που πρέπει να παρακολουθήσετε εάν αντιμετωπίζετε υψηλή χρήση μνήμης και σχετική υπερβολική σελιδοποίηση. Αυτός ο μετρητής χαρακτηρίζει το ποσό της εναλλαγής και η κανονική (όχι η μέγιστη) τιμή του πρέπει να είναι κοντά στο μηδέν. Η αύξηση της ανταλλαγής υποδηλώνει την ανάγκη αύξησης της μνήμης RAM ή μείωσης του αριθμού των εφαρμογών που εκτελούνται στον διακομιστή.

      Zabbix: perf_counter[MemoryPages/sec] Παράδειγμα ενεργοποίησης:
      {NOTE_NAME:perf_counter[MemoryPages/sec].min(5m)}>1000, level-info

    2. Σφάλματα σελίδας/δευτ

      Αυτή είναι η τιμή του μετρητή σφαλμάτων σελίδας. Ένα σφάλμα σελίδας προκύπτει όταν μια διεργασία αναφέρεται σε μια σελίδα εικονικής μνήμης που δεν βρίσκεται στο σύνολο εργασίας της μνήμης RAM. Αυτός ο μετρητής λαμβάνει υπόψη τόσο τα σφάλματα σελίδας που απαιτούν πρόσβαση στο δίσκο όσο και αυτά που προκαλούνται από τη θέση της σελίδας εκτός του συνόλου εργασίας στη μνήμη RAM. Οι περισσότεροι επεξεργαστές μπορούν να χειριστούν σφάλματα σελίδας τύπου XNUMX χωρίς μεγάλη καθυστέρηση. Ωστόσο, ο χειρισμός σφαλμάτων σελίδας τύπου XNUMX, που απαιτούν πρόσβαση στο δίσκο, μπορεί να προκαλέσει σημαντικές καθυστερήσεις.

      Zabbix: perf_counter[Σφάλματα MemoryPage/sec] Παράδειγμα ενεργοποίησης:
      {NODE_NAME:perf_counter[MemoryPage Faults/sec].min(5m)}>1000, πληροφορίες επιπέδου

    3. Διαθέσιμα Byte

      Παρακολουθεί την ποσότητα της μνήμης σε byte που είναι διαθέσιμη για την εκτέλεση διαφόρων διεργασιών. Χαμηλοί αριθμοί σημαίνουν χαμηλή μνήμη. Η λύση είναι η αύξηση της μνήμης. Αυτός ο μετρητής θα πρέπει στις περισσότερες περιπτώσεις να είναι συνεχώς πάνω από 5000 kV.
      Είναι λογικό να ορίσετε το όριο για τα Διαθέσιμα Mbyte με μη αυτόματο τρόπο για τους ακόλουθους λόγους:

      •50% δωρεάν μνήμη διαθέσιμη = Εξαιρετική
      •25% διαθέσιμη μνήμη = Χρειάζεται προσοχή
      •10% δωρεάν = Πιθανά προβλήματα
      •Λιγότερο από 5% διαθέσιμη μνήμη = Κρίσιμο για την ταχύτητα, πρέπει να παρέμβετε.
      Zabbix: perf_counter[MemoryAvailable Bytes]

  3. Επεξεργαστής (Σύνολο): % Χρόνος Επεξεργαστή
    Αυτός ο μετρητής δείχνει το ποσοστό του χρόνου που ο επεξεργαστής ήταν απασχολημένος με την εκτέλεση λειτουργιών για μη αδρανή νήματα (non-Idle thread). Αυτή η τιμή μπορεί να θεωρηθεί ως ένα κλάσμα του χρόνου που απαιτείται για την εκτέλεση χρήσιμης εργασίας. Κάθε επεξεργαστής μπορεί να αντιστοιχιστεί σε ένα αδρανές νήμα που καταναλώνει μη παραγωγικούς κύκλους επεξεργαστή που δεν χρησιμοποιούνται από άλλα νήματα. Αυτός ο μετρητής χαρακτηρίζεται από μικρές κορυφές που μπορούν να φτάσουν το 100 τοις εκατό. Ωστόσο, εάν υπάρχουν εκτεταμένες περίοδοι όπου η χρήση του επεξεργαστή είναι πάνω από 80 τοις εκατό, τότε το σύστημα θα είναι πιο αποτελεσματικό όταν χρησιμοποιεί περισσότερους επεξεργαστές.

    Zabbix: perf_counter[Processor(_Total)% Processor Time], εδώ μπορεί επίσης να εμφανιστεί ανά πυρήνες
    Παράδειγμα ενεργοποίησης:
    {NODE_NAME:perf_counter[Processor(_Total)% Processor Time].min(5m)}>80, level-info

  4. Διεπαφή δικτύου (*): % Byte Σύνολο/δευτ
    Ο συνολικός αριθμός των byte που αποστέλλονται και λαμβάνονται ανά δευτερόλεπτο σε όλες τις διεπαφές. Αυτό είναι το εύρος ζώνης διεπαφής (σε byte). Είναι απαραίτητο να συγκρίνετε την τιμή αυτού του μετρητή με το μέγιστο εύρος ζώνης της κάρτας δικτύου. Γενικά, αυτός ο μετρητής δεν πρέπει να εμφανίζει περισσότερο από 50% χρήση εύρους ζώνης προσαρμογέα δικτύου.
    Zabbix: perf_counter[Διασύνδεση δικτύου(*)Bytes Sent/sec]
  5. MS SQL Server: Μέθοδοι πρόσβασης
    Το αντικείμενο Access Methods στον SQL Server παρέχει μετρητές που βοηθούν στην παρακολούθηση της πρόσβασης σε λογικά δεδομένα μέσα σε μια βάση δεδομένων. Η φυσική πρόσβαση σε σελίδες βάσης δεδομένων στο δίσκο ελέγχεται από μετρητές διαχείρισης buffer. Η παρατήρηση μεθόδων πρόσβασης δεδομένων σε μια βάση δεδομένων σάς βοηθά να προσδιορίσετε εάν μπορείτε να βελτιώσετε την απόδοση του ερωτήματος προσθέτοντας ή αλλάζοντας ευρετήρια, προσθέτοντας ή μετακινώντας διαμερίσματα, προσθέτοντας αρχεία ή ομάδες αρχείων, ανασυγκροτώντας ευρετήρια ή αλλάζοντας κείμενο ερωτήματος. Μπορείτε επίσης να χρησιμοποιήσετε τους μετρητές στο αντικείμενο Μέθοδοι πρόσβασης για να παρακολουθείτε το μέγεθος των δεδομένων, τα ευρετήρια και τον ελεύθερο χώρο στη βάση δεδομένων, ελέγχοντας τον όγκο και τον κατακερματισμό για κάθε παρουσία διακομιστή. Ο υπερβολικός κατακερματισμός του ευρετηρίου μπορεί να υποβαθμίσει σημαντικά την απόδοση.

    1. Διαχωρίσεις σελίδων/δευτ
      Ο αριθμός των αλλαγών σελίδας ανά δευτερόλεπτο που προέκυψαν ως αποτέλεσμα υπερχείλισης σελίδας ευρετηρίου. Μια μεγάλη τιμή αυτού του δείκτη σημαίνει ότι ο SQL Server εκτελεί έναν μεγάλο αριθμό λειτουργιών έντασης πόρων για να χωρίσει σελίδες και να μετακινήσει μέρος μιας υπάρχουσας σελίδας σε μια νέα θέση κατά την εκτέλεση εργασιών εισαγωγής και ενημέρωσης. Τέτοιες εργασίες θα πρέπει να αποφεύγονται όποτε είναι δυνατόν. Μπορείτε να προσπαθήσετε να λύσετε το πρόβλημα με δύο τρόπους:
      - Δημιουργήστε ένα συγκεντρωμένο ευρετήριο σε στήλες αυτόματης αύξησης. Σε αυτήν την περίπτωση, οι νέες εγγραφές δεν θα τοποθετούνται μέσα σε σελίδες που έχουν ήδη καταληφθεί από δεδομένα, αλλά θα καταλαμβάνουν διαδοχικά νέες σελίδες.
      — αναδημιουργήστε ευρετήρια αυξάνοντας την τιμή της παραμέτρου Fillfactor. Αυτή η επιλογή επιτρέπει τη δέσμευση ελεύθερου χώρου στις σελίδες ευρετηρίου για νέα δεδομένα χωρίς την ανάγκη σελιδοποίησης.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Access MethodsPage Splits/sec",30] Παράδειγμα ενεργοποίησης: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Access MethodsPage Splits/sec",30].last()}>{NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:SQL Statistics Batch Requests/sec",(30]] /5, επίπεδο-πληροφορίες
    2. Πλήρεις σαρώσεις/δευτ
      Ο αριθμός των απεριόριστων πλήρους σαρώσεων ανά δευτερόλεπτο. Αυτές οι λειτουργίες περιλαμβάνουν σαρώσεις βασικού πίνακα και σαρώσεις πλήρους ευρετηρίου. Μια σταθερή αύξηση αυτού του δείκτη μπορεί να υποδηλώνει υποβάθμιση του συστήματος (έλλειψη απαραίτητων ευρετηρίων, ισχυρός κατακερματισμός τους, μη χρήση υπαρχόντων ευρετηρίων από τον βελτιστοποιητή, παρουσία αχρησιμοποίητων ευρετηρίων). Ωστόσο, αξίζει να σημειωθεί ότι μια πλήρης σάρωση σε μικρά τραπέζια δεν είναι πάντα κακή, γιατί εάν μπορείτε να χωρέσετε ολόκληρο το τραπέζι στη μνήμη RAM, τότε θα είναι απλώς πιο γρήγορο να εκτελέσετε μια πλήρη σάρωση. Αλλά στις περισσότερες περιπτώσεις, μια σταθερή ανάπτυξη αυτού του μετρητή θα υποδηλώνει την υποβάθμιση του συστήματος. Όλα αυτά ισχύουν μόνο για συστήματα OLTP. Στα συστήματα OLAP, οι συνεχείς πλήρεις σαρώσεις είναι φυσιολογικές.
      Zabbix: perf_counter["MSSQL$InstanceName:Access MethodsFull Scans/sec",30]

  6. MS SQL Server: Buffer Manager
    Το αντικείμενο Buffer Manager παρέχει μετρητές για την παρακολούθηση του τρόπου με τον οποίο ο SQL Server χρησιμοποιεί τους ακόλουθους πόρους:
    - μνήμη για την αποθήκευση σελίδων δεδομένων.
    - μετρητές που χρησιμοποιούνται για την παρακολούθηση της φυσικής I/O όταν ο SQL Server διαβάζει και γράφει σελίδες βάσης δεδομένων.
    - Επέκταση χώρου αποθήκευσης buffer για επέκταση της προσωρινής μνήμης buffer χρησιμοποιώντας γρήγορη μη πτητική μνήμη, όπως μονάδες SSD.
    - Η παρακολούθηση της μνήμης και των μετρητών που χρησιμοποιούνται από τον SQL Server βοηθά στη λήψη των ακόλουθων πληροφοριών.
    - Υπάρχουν «συμφορήσεις» που προκαλούνται από έλλειψη φυσικής μνήμης. Εάν τα δεδομένα με συχνή πρόσβαση δεν μπορούν να αποθηκευτούν προσωρινά, ο SQL Server αναγκάζεται να τα διαβάσει από το δίσκο.
    - Εάν είναι δυνατό να αυξηθεί η αποτελεσματικότητα της εκτέλεσης ερωτημάτων αυξάνοντας την ποσότητα της μνήμης ή εκχωρώντας πρόσθετη μνήμη για την προσωρινή αποθήκευση δεδομένων ή την αποθήκευση εσωτερικών δομών του SQL Server.
    Πόσο συχνά ο SQL Server διαβάζει δεδομένα από το δίσκο. Σε σύγκριση με άλλες λειτουργίες, όπως η πρόσβαση στη μνήμη, η φυσική I/O διαρκεί περισσότερο. Η μείωση του I/O μπορεί να βελτιώσει την απόδοση του ερωτήματος.

    1. Το Buffer Cache χτύπησε το ραδιόφωνο
      Υποδεικνύει πόσο πλήρως ο SQL Server μπορεί να εκχωρήσει δεδομένα στην προσωρινή μνήμη προσωρινής αποθήκευσης. Όσο μεγαλύτερη είναι αυτή η τιμή, τόσο το καλύτερο. Για να έχει ο SQL Server αποτελεσματική πρόσβαση σε σελίδες δεδομένων, αυτές πρέπει να βρίσκονται σε προσωρινή μνήμη προσωρινής αποθήκευσης και δεν πρέπει να υπάρχουν λειτουργίες φυσικής εισόδου/εξόδου (I/O). Εάν υπάρχει σταθερή μείωση στη μέση τιμή αυτού του μετρητή, θα πρέπει να εξετάσετε το ενδεχόμενο προσθήκης μνήμης RAM. Αυτός ο δείκτης θα πρέπει πάντα να είναι πάνω από 90% για συστήματα OLTP και πάνω από 50% για συστήματα OLAP.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Buffer ManagerBuffer αναλογία επίσκεψης προσωρινής μνήμης",30] Παραδείγματα ενεργοποίησης: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Buffer ManagerBuffer ratio hit cache",30].last()}<70, level-high
      и
      {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Buffer ManagerBuffer ratio hit cache",30].last()}<80, level-medium
    2. Προσδόκιμο ζωής σελίδας
      Υποδεικνύει πόσο καιρό η σελίδα θα παραμείνει μόνιμα στη μνήμη στην τρέχουσα κατάστασή της. Εάν η τιμή συνεχίζει να πέφτει, σημαίνει ότι το σύστημα χρησιμοποιεί υπερβολικά το buffer pool. Έτσι, η λειτουργία της μνήμης μπορεί ενδεχομένως να προκαλέσει προβλήματα που οδηγούν σε υποβάθμιση της απόδοσης. Αξίζει να σημειωθεί ότι δεν υπάρχει καθολική ένδειξη κάτω από την οποία μπορεί κανείς να κρίνει κατηγορηματικά ότι το σύστημα κάνει κατάχρηση του buffer pool (η ένδειξη των 300 δευτερολέπτων είναι ξεπερασμένη με τον MS SQL Server 2012).
      Zabbix: perf_counter["MSSQL$INSTENTION_NAME:Buffer ManagerPage προσδόκιμο ζωής",30] Παράδειγμα ενεργοποίησης: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Buffer ManagerPage προσδόκιμο ζωής",30].last()}<5, επίπεδο-πληροφορίες

  7. MS SQL Server: Γενικά στατιστικά
    Το αντικείμενο General Statistics στον SQL Server παρέχει μετρητές που σας επιτρέπουν να παρακολουθείτε τη συνολική δραστηριότητα διακομιστή, όπως τον αριθμό των ταυτόχρονων συνδέσεων και τον αριθμό των χρηστών ανά δευτερόλεπτο που συνδέονται ή αποσυνδέονται από τον υπολογιστή που εκτελεί μια παρουσία του SQL Server. Αυτές οι μετρήσεις είναι χρήσιμες σε συστήματα επεξεργασίας μεγάλων διαδικτυακών συναλλαγών (OLTP) όπου ένας μεγάλος αριθμός πελατών συνδέεται και αποσυνδέεται συνεχώς από την παρουσία του SQL Server.

    1. Η διαδικασία μπλοκαρίστηκε
      Ο αριθμός των διαδικασιών που έχουν αποκλειστεί αυτήν τη στιγμή.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Οι διαδικασίες γενικών στατιστικών έχουν αποκλειστεί",30] Παράδειγμα ενεργοποίησης: ({NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:General StatisticsProcesses blocked",30].min(2m,0)}>=0)
      και ({NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:General StatisticsProcesses blocked",30].time(0)}>=50000)
      και ({NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:General StatisticsProcesses blocked",30].time(0)}<=230000), πληροφορίες επιπέδου (υπάρχει περιορισμός συναγερμού από τις 05:00 έως τις 23:00)
    2. Συνδέσεις χρήστη
      Ο αριθμός των χρηστών που είναι συνδεδεμένοι αυτήν τη στιγμή στον SQL Server.
      Zabbix: perf_counter["MSSQL$INSPECTION_NAME:General StatisticsUser Connections",30]

  8. MS SQL Server: Κλειδαριές
    Το αντικείμενο Locks στον Microsoft SQL Server παρέχει πληροφορίες σχετικά με τα κλειδώματα του SQL Server που αποκτήθηκαν σε μεμονωμένους τύπους πόρων. Οι κλειδαριές εκδίδονται σε πόρους του SQL Server, όπως σειρές που διαβάζονται ή τροποποιούνται από μια συναλλαγή, για να αποτρέπεται η ταυτόχρονη χρήση των πόρων από πολλές συναλλαγές. Για παράδειγμα, εάν ένα αποκλειστικό κλείδωμα (X) αποκτηθεί από μια συναλλαγή σε μια σειρά σε έναν πίνακα, καμία άλλη συναλλαγή δεν μπορεί να τροποποιήσει αυτήν τη σειρά μέχρι να απελευθερωθεί η κλειδαριά. Η ελαχιστοποίηση της χρήσης κλειδαριών αυξάνει τη συγχρονικότητα, η οποία μπορεί να βελτιώσει τη συνολική απόδοση. Πολλαπλές παρουσίες του αντικειμένου Locks μπορούν να παρακολουθηθούν ταυτόχρονα, καθεμία από τις οποίες θα αντιπροσωπεύει ένα κλείδωμα σε διαφορετικό τύπο πόρου.

    1. Μέσος χρόνος αναμονής (ms)
      Ο μέσος χρόνος αναμονής (σε χιλιοστά του δευτερολέπτου) για όλα τα αιτήματα κλειδώματος που απαιτούσαν αναμονή. Αυτός ο μετρητής μετρά τον μέσο αριθμό διεργασιών χρήστη που πρέπει να περιμένουν στην ουρά για να αποκτήσουν ένα κλείδωμα σε έναν πόρο. Η μέγιστη επιτρεπόμενη τιμή αυτού του μετρητή εξαρτάται αποκλειστικά από την εργασία σας, είναι δύσκολο να προσδιορίσετε μια μέση τιμή για όλες τις εφαρμογές εδώ. Εάν αυτός ο μετρητής είναι πολύ υψηλός, μπορεί να σημαίνει προβλήματα με κλειδώματα στη βάση δεδομένων σας.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Μέσος χρόνος αναμονής (ms)",30] Παράδειγμα ενεργοποίησης: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Average Wait Time (ms)",30].last()}>=500, level-info
    2. Κλείδωμα χρόνου αναμονής (ms)
      Συνολικός χρόνος αναμονής κλειδώματος (σε χιλιοστά του δευτερολέπτου) στο τελευταίο δευτερόλεπτο.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Wait Time (ms)",30]
    3. Κλείδωμα Περιμένει/δευτ
      Πόσες φορές το τελευταίο δευτερόλεπτο χρειάστηκε να περιμένει ένα νήμα για αίτημα κλειδώματος.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Waits/sec",30]
    4. Χρονικά όρια κλειδώματος/δευτ
      Ο αριθμός των επαναλήψεων όταν η κλειδαριά δεν μπορεί να αποκτηθεί με round-robin. Η τιμή της παραμέτρου διαμόρφωσης μετρητή περιστροφών του SQL Server καθορίζει τον αριθμό των "στροφών" του νήματος (περιστροφές) προτού λήξει το χρονικό διάστημα και το νήμα παραμείνει αδρανές.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Timeouts/sec",30] Παράδειγμα ενεργοποίησης: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Locks(_Total)Lock Timeouts/sec",30].last()}>1000, level-info
    5. Αιτήματα κλειδώματος/δευτ
      Ο αριθμός των αιτημάτων ανά δευτερόλεπτο για τον καθορισμένο τύπο κλειδώματος.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Αιτήματα κλειδώματος/δευτ.",30] Παράδειγμα ενεργοποίησης: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Lock Requests/sec",30].last()}>500000, επίπεδο πληροφοριών
    6. Κλείδωμα Αριθμός αδιεξόδων/δευτ
      Ο αριθμός των αιτημάτων κλειδώματος ανά δευτερόλεπτο που οδηγούν σε αδιέξοδο. Τα αδιέξοδα υποδεικνύουν ερωτήματα με λανθασμένη μορφή που μπλοκάρουν κοινόχρηστους πόρους.
      Zabbix: perf_counter["MSSQL$INSTENTION_NAME:Αριθμός αδιεξόδων/δευτ.",30] Παράδειγμα ενεργοποίησης: {NODE_NAME:perf_counter["MSSQL$INSPECTION_NAME:Locks(_Total)Number of Deadlocks/sec",30].last()}>1, υψηλό επίπεδο

  9. MS SQL Server: Διαχείριση μνήμης
    Το αντικείμενο Memory Manager στον Microsoft SQL Server παρέχει μετρητές για την παρακολούθηση της χρήσης της μνήμης σε όλο το διακομιστή. Η παρακολούθηση της χρήσης μνήμης σε όλο τον διακομιστή για την αξιολόγηση της δραστηριότητας του χρήστη και της χρήσης πόρων μπορεί να βοηθήσει στον εντοπισμό των σημείων συμφόρησης απόδοσης. Το στοιχείο ελέγχου μνήμης που χρησιμοποιείται από μια παρουσία του SQL Server μπορεί να βοηθήσει στον προσδιορισμό:
    - Εάν υπάρχουν ελλείψεις σε ανεπαρκή φυσική μνήμη για την αποθήκευση δεδομένων με συχνή πρόσβαση στην κρυφή μνήμη. Εάν δεν υπάρχει αρκετή μνήμη, ο SQL Server πρέπει να ανακτήσει τα δεδομένα από το δίσκο.
    - Εάν η απόδοση του ερωτήματος θα μπορούσε να βελτιωθεί εάν προστεθεί μνήμη ή αν αυξηθεί η ποσότητα της διαθέσιμης μνήμης για την προσωρινή αποθήκευση δεδομένων ή τις εσωτερικές δομές του SQL Server.

    1. Εξαιρετικές επιχορηγήσεις μνήμης
      Καθορίζει τον συνολικό αριθμό διεργασιών που απέκτησαν επιτυχώς μνήμη χώρου εργασίας. Με μια σταθερή πτώση του δείκτη, είναι απαραίτητο να αυξήσετε τη μνήμη RAM.
      Zabbix: perf_counter["MSSQL$INSTENTION_NAME:Εξαιρετικές επιχορηγήσεις μνήμης στον διαχειριστή μνήμης",30]
    2. Επιχορηγήσεις μνήμης σε εκκρεμότητα
      Υποδεικνύει τον συνολικό αριθμό διεργασιών που περιμένουν να εκχωρηθεί η μνήμη εργασίας. Με σταθερή ανάπτυξη του δείκτη, είναι απαραίτητο να αυξηθεί η μνήμη RAM.
      Zabbix: perf_counter["MSSQL$InstanceName:Memory ManagerMemory Grants σε εκκρεμότητα",30]

  10. MS SQL Server: Στατιστικά
    Το αντικείμενο Statistics στον Microsoft SQL Server παρέχει μετρητές για την παρακολούθηση τύπων μεταγλώττισης και ερωτημάτων που αποστέλλονται σε μια παρουσία του SQL Server. Η παρακολούθηση του αριθμού των μεταγλωττίσεων ερωτημάτων και των αναμεταγλωττίσεων και του αριθμού των παρτίδων που λαμβάνονται από μια παρουσία του SQL Server σάς δίνει μια ιδέα για το πόσο γρήγορα ο SQL Server εκτελεί τα ερωτήματα των χρηστών και πόσο αποτελεσματικά τα επεξεργάζεται το εργαλείο βελτιστοποίησης ερωτημάτων.

    1. Αιτήσεις παρτίδας/δευτ
      Ο αριθμός των πακέτων εντολών Transact-SQL που λαμβάνονται ανά δευτερόλεπτο. Αυτά τα στατιστικά στοιχεία επηρεάζονται από τυχόν όρια (I/O, αριθμός χρηστών, μέγεθος προσωρινής μνήμης, πολυπλοκότητα ερωτήματος κ.λπ.). Ένας μεγάλος αριθμός αιτημάτων πακέτων υποδηλώνει υψηλή απόδοση.
      Zabbix: perf_counter["MSSQL$InstanceName:SQL StatisticsBatch Requests/sec",30]

Εκτός από όλα τα παραπάνω, μπορείτε επίσης να διαμορφώσετε άλλα στοιχεία δεδομένων (καθώς και να δημιουργήσετε ενεργοποιητές σε αυτά με επακόλουθη ειδοποίηση). Για παράδειγμα:
1) ελεύθερος χώρος στο δίσκο
2) μεγέθη αρχείων και αρχείων καταγραφής δεδομένων βάσης δεδομένων
κ.λπ.
Ωστόσο, όλοι αυτοί οι δείκτες δεν δείχνουν το πρόβλημα των ερωτημάτων σε πραγματικό χρόνο.
Για να το κάνετε αυτό, πρέπει να δημιουργήσετε τους δικούς σας ειδικούς μετρητές.
Για λόγους εμπιστευτικότητας, δεν θα δώσω παραδείγματα τέτοιων μετρητών. Επιπλέον, διαμορφώνονται μοναδικά για κάθε σύστημα. Σημειώνω όμως ότι για συστήματα όπως 1C, 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 / Create a request directly to MSSQL
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand;
$SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure;  
$SqlCmd.CommandText = "nav.ZabbixGetCountRequestStatus";
$SqlCmd.Connection = $Connection;

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

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

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

write-host $result;

Κωδικός για εκκρεμή αιτήματα

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

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

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

#Создаем запрос непосредственно к MSSQL / Create a request directly to MSSQL
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand;
$SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure;  
$SqlCmd.CommandText = "nav.ZabbixGetCountRequestStatus";
$SqlCmd.Connection = $Connection;

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

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

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

write-host $result;

Τώρα πρέπει να δημιουργήσετε ένα αρχείο με παραμέτρους χρήστη και μια επέκταση .conf (ή να προσθέσετε γραμμές σε ένα υπάρχον τέτοιο αρχείο χρήστη, εάν δημιουργήθηκε νωρίτερα) και να εισαγάγετε τις ακόλουθες γραμμές:
UserParameter=PARAMETER_NAME_NUMBER_of_EXECUTED_QUERY,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILE_NAME_FOR_EXECUTED_QUERY.ps1
UserParameter=PARAMETER_NAME_NUMBER_of_PENDING_REQUESTS,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILE_NAME_FOR_PENDING_REQUESTS.ps1
Μετά από αυτό, αποθηκεύουμε το αρχείο .conf και επανεκκινούμε τον παράγοντα Zabbix.
Μετά από αυτό, προσθέτουμε δύο νέα στοιχεία στο Zabbix (σε αυτήν την περίπτωση, τα ονόματα και το κλειδί είναι τα ίδια):
NAME_PARAMETER_NUMBER_PERFORMED_QUERY
NAME_PARAMETER_NUMBER_PENDING_REQUESTS
Τώρα μπορείτε να δημιουργήσετε γραφήματα και κανόνες ετικέτας στα προσαρμοσμένα στοιχεία που δημιουργήσατε.

Εάν ο αριθμός των εκκρεμών αιτημάτων αυξηθεί απότομα, τότε το επόμενο ερώτημα μπορεί να εμφανίσει όλα τα αιτήματα που εκτελούνται και τα εκκρεμή σε μια δεδομένη στιγμή με λεπτομέρειες από πού και κάτω από ποια σύνδεση εκτελείται το αίτημα, το κείμενο και το σχέδιο ερωτήματος, καθώς και άλλες λεπτομέρειες:
Κώδικας

/*Активные, готовые к выполнению и ожидающие запросы, а также те, что явно блокируют другие сеансы*/
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-connector-net και μετά γράψε κώδικα ως εξής:
Κωδικός για εκκρεμή αιτήματα

#Задаем переменные для подключение к 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. Αυτή η προσέγγιση σάς επιτρέπει να ειδοποιείτε τους διαχειριστές για διάφορα προβλήματα σε πραγματικό χρόνο ή μετά από ορισμένο χρόνο. Έτσι, αυτή η προσέγγιση επιτρέπει την ελαχιστοποίηση της εμφάνισης ενός κρίσιμου προβλήματος στο μέλλον και τη διακοπή της λειτουργίας του DBMS και του διακομιστή, ο οποίος με τη σειρά του προστατεύει την παραγωγή από τη διακοπή των διαδικασιών εργασίας.
Προηγούμενο άρθρο: Εργασία ρουτίνας με τη βάση δεδομένων του συστήματος πληροφοριών 24×7 στον MS SQL Server

Πηγές:

» Zabbix 3.4
» Μετρητές απόδοσης
» Κέντρο απόδοσης για τη βάση δεδομένων Azure SQL και τη μηχανή βάσης δεδομένων SQL Server
» SQL Lifestyle
» SQLSskills
» Microsoft TechNet
» Ανάλυση χρήσης μνήμης
» Ανάλυση Απόδοσης
» Τεκμηρίωση SQL
» Σημειώσεις σχετικά με τα Windows

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο