Sử dụng Zabbix để giám sát cơ sở dữ liệu máy chủ MS SQL

lời tựa

Thường xuyên có nhu cầu báo cáo cho người quản trị theo thời gian thực về các vấn đề liên quan đến cơ sở dữ liệu (database).

Bài viết này sẽ mô tả những gì cần được cấu hình trong Zabbix để giám sát cơ sở dữ liệu MS SQL Server.

Xin lưu ý rằng chi tiết về cách định cấu hình sẽ không được cung cấp, tuy nhiên, các công thức và đề xuất chung cũng như mô tả chi tiết về việc thêm các thành phần dữ liệu tùy chỉnh thông qua các quy trình được lưu trữ sẽ được cung cấp trong bài viết này.
Ngoài ra, chỉ có các bộ đếm hiệu suất chính sẽ được thảo luận ở đây.

phán quyết

Đầu tiên, tôi sẽ mô tả tất cả các bộ đếm hiệu suất (thông qua các phần tử dữ liệu trong Zabbix) mà chúng ta cần:

  1. Đĩa logic
    1. Đĩa trung bình giây/Đọc
      Hiển thị thời gian trung bình, tính bằng giây, để đọc dữ liệu từ đĩa. Giá trị trung bình của bộ đếm hiệu suất trung bình. Đĩa giây/Đọc không được vượt quá 10 mili giây. Giá trị tối đa của bộ đếm hiệu suất Avg. Đĩa giây/Đọc không được vượt quá 50 mili giây.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Đĩa giây/Đọc] và điều quan trọng là phải theo dõi đĩa mong muốn, ví dụ như sau: perf_counter[LogicalDisk(C:)Avg. Đĩa giây/Đọc]

      Ví dụ kích hoạt:
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Đĩa giây/Đọc].last()}>0.005, mức cao
      и
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Đĩa giây/Đọc].last()}>0.0025, mức trung bình

    2. Đĩa trung bình giây/Ghi
      Hiển thị thời gian trung bình, tính bằng giây, để ghi dữ liệu vào đĩa. Giá trị trung bình của bộ đếm hiệu suất trung bình. Đĩa giây/Ghi không được vượt quá 10 mili giây. Giá trị tối đa của bộ đếm hiệu suất Avg. Đĩa giây/Ghi không được vượt quá 50 mili giây.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Disk sec/Write] và điều quan trọng là phải theo dõi ổ đĩa mong muốn, ví dụ như sau: perf_counter[LogicalDisk(C:)Avg. Đĩa giây/Ghi]

      Ví dụ kích hoạt:
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Đĩa giây/Ghi].last()}>0.005, mức cao
      и
      {NODE_NAME:perf_counter[LogicalDisk(_Total)Avg. Đĩa giây/Ghi].last()}>0.0025, mức trung bình

    3. Độ dài hàng đợi đĩa trung bình

      Độ dài hàng đợi trung bình của các yêu cầu tới đĩa. Hiển thị số lượng yêu cầu đĩa đang chờ xử lý trong một khoảng thời gian nhất định. Hàng đợi không quá 2 cho một đĩa được coi là bình thường. Nếu có nhiều hơn hai yêu cầu trong hàng đợi thì đĩa có thể bị quá tải và không thể xử lý các yêu cầu đến. Bạn có thể tìm ra chính xác những thao tác nào mà đĩa không thể xử lý bằng cách sử dụng bộ đếm Trung bình. Độ dài hàng đợi đọc đĩa và trung bình Độ dài hàng đợi của Disk Wright (hàng đợi yêu cầu ghi).
      Giá trị trung bình Độ dài hàng đợi đĩa không được đo mà được tính bằng định luật Little từ lý thuyết toán học về hàng đợi. Theo luật này, số lượng yêu cầu đang chờ xử lý trung bình bằng tần suất yêu cầu nhân với thời gian xử lý yêu cầu. Những thứ kia. trong trường hợp của chúng tôi Độ dài hàng đợi đĩa = (Số lần truyền đĩa/giây) * (Số giây đĩa trung bình/Truyền chuyển).

      Trung bình Độ dài hàng đợi đĩa được đưa ra như một trong những bộ đếm chính để xác định tải trên hệ thống con đĩa, tuy nhiên, để đánh giá đầy đủ nó, cần phải thể hiện chính xác cấu trúc vật lý của hệ thống lưu trữ. Ví dụ: đối với một ổ cứng, giá trị lớn hơn 2 được coi là quan trọng và nếu đĩa nằm trên mảng RAID gồm 4 đĩa thì bạn nên lo lắng nếu giá trị đó lớn hơn 4*2=8.

      Zabbix: perf_counter[LogicalDisk(_Total)Avg. Độ dài hàng đợi đĩa] và điều quan trọng là phải theo dõi đĩa mong muốn, ví dụ như sau: perf_counter[LogicalDisk(C:)Avg. Độ dài hàng đợi đĩa]

  2. Bộ nhớ
    1. Trang/giây
      Hiển thị số trang mà SQL Server đọc từ đĩa hoặc ghi vào đĩa để giải quyết các quyền truy cập vào các trang bộ nhớ không được tải vào RAM tại thời điểm truy cập. Giá trị này là tổng của Số trang đầu vào/giây và Số trang đầu ra/giây, đồng thời cũng tính đến khả năng phân trang (phân trang/hoán đổi) của bộ đệm hệ thống để truy cập các tệp dữ liệu ứng dụng. Ngoài ra, điều này bao gồm phân trang các tệp không được lưu trong bộ nhớ đệm được ánh xạ trực tiếp vào bộ nhớ. Đây là bộ đếm chính cần được theo dõi nếu bạn đang gặp phải tình trạng sử dụng bộ nhớ cao và phân trang quá mức liên quan. Bộ đếm này đặc trưng cho lượng hoán đổi và giá trị bình thường (không phải đỉnh) của nó phải gần bằng XNUMX. Việc trao đổi tăng lên cho thấy nhu cầu tăng RAM hoặc giảm số lượng chương trình ứng dụng đang chạy trên máy chủ.

      Zabbix: perf_counter[Trang bộ nhớ/giây] Ví dụ kích hoạt:
      {NODE_NAME:perf_counter[MemoryPages/sec].min(5m)}>1000, thông tin cấp độ

    2. Lỗi trang/giây

      Đây là giá trị bộ đếm lỗi trang. Lỗi trang xảy ra khi một quá trình tham chiếu đến một trang bộ nhớ ảo không có trong bộ RAM đang hoạt động. Bộ đếm này tính đến cả các lỗi trang yêu cầu quyền truy cập vào đĩa và các lỗi do trang nằm ngoài bộ làm việc trong RAM gây ra. Hầu hết các bộ xử lý có thể xử lý lỗi trang Loại XNUMX mà không bị chậm trễ nhiều. Tuy nhiên, việc xử lý lỗi trang loại XNUMX yêu cầu quyền truy cập vào đĩa có thể gây ra sự chậm trễ đáng kể.

      Zabbix: perf_counter[Lỗi trang bộ nhớ/giây] Ví dụ kích hoạt:
      {NODE_NAME:perf_counter[Lỗi trang bộ nhớ/giây].min(5m)}>1000, thông tin cấp độ

    3. Byte có sẵn

      Theo dõi lượng bộ nhớ có sẵn tính bằng byte để chạy các tiến trình khác nhau. Số đọc thấp cho thấy bộ nhớ thấp. Giải pháp là tăng cường trí nhớ. Đồng hồ này trong hầu hết các trường hợp phải liên tục ở mức trên 5000 kV.
      Việc đặt ngưỡng cho Mbyte khả dụng theo cách thủ công là điều hợp lý vì những lý do sau:

      •Có 50% bộ nhớ trống = Xuất sắc
      •25% bộ nhớ khả dụng = Cần chú ý
      •10% miễn phí = Các vấn đề có thể xảy ra
      •Bộ nhớ khả dụng dưới 5% = Quan trọng về tốc độ, bạn cần can thiệp.
      Zabbix: perf_counter[Bộ nhớ có sẵn Byte]

  3. Bộ xử lý (Tổng cộng): % Thời gian xử lý
    Bộ đếm này hiển thị phần trăm thời gian mà bộ xử lý bận thực hiện các hoạt động đối với các luồng không nhàn rỗi. Giá trị này có thể được coi là tỷ lệ thời gian dành cho việc làm có ích. Mỗi bộ xử lý có thể được gán cho một luồng nhàn rỗi, điều này tiêu tốn các chu kỳ xử lý không hiệu quả mà các luồng khác không sử dụng. Bộ đếm này được đặc trưng bởi các đỉnh ngắn có thể đạt tới 100 phần trăm. Tuy nhiên, nếu có những khoảng thời gian dài mà mức sử dụng bộ xử lý trên 80% thì hệ thống sẽ hiệu quả hơn khi sử dụng nhiều bộ xử lý hơn.

    Zabbix: perf_counter[Bộ xử lý (_Total)% Thời gian xử lý], ở đây nó cũng có thể được hiển thị theo lõi
    Ví dụ kích hoạt:
    {NODE_NAME:perf_counter[Bộ xử lý(_Total)% Thời gian xử lý].min(5m)}>80, thông tin cấp độ

  4. Giao diện mạng (*): % Byte Tổng/giây
    Tổng số byte được gửi và nhận mỗi giây trên tất cả các giao diện. Đây là băng thông giao diện (tính bằng byte). Cần phải so sánh giá trị của bộ đếm này với băng thông tối đa của card mạng. Nói chung, bộ đếm này sẽ hiển thị mức sử dụng không quá 50% băng thông của bộ điều hợp mạng.
    Zabbix: perf_counter[Giao diện mạng(*)Byte đã gửi/giây]
  5. Máy chủ MS SQL: Phương thức truy cập
    Đối tượng Phương thức truy cập trong SQL Server cung cấp bộ đếm để giúp theo dõi quyền truy cập vào dữ liệu logic trong cơ sở dữ liệu. Quyền truy cập vật lý vào các trang cơ sở dữ liệu trên đĩa được kiểm soát bằng bộ đếm quản lý bộ đệm. Giám sát các phương pháp truy cập dữ liệu trong cơ sở dữ liệu giúp xác định xem có thể cải thiện hiệu suất truy vấn bằng cách thêm hoặc thay đổi chỉ mục, thêm hoặc di chuyển phân vùng, thêm tệp hoặc nhóm tệp, chống phân mảnh chỉ mục hoặc thay đổi văn bản truy vấn. Ngoài ra, bạn có thể sử dụng bộ đếm đối tượng của Phương thức truy cập để giám sát kích thước dữ liệu, chỉ mục và dung lượng trống trong cơ sở dữ liệu của mình, cũng như khả năng giám sát và phân mảnh cho từng phiên bản máy chủ. Phân mảnh chỉ mục quá mức có thể làm giảm đáng kể hiệu suất.

    1. Số lần chia trang/giây
      Số lần chia trang mỗi giây được thực hiện do tràn trang chỉ mục. Giá trị cao cho số liệu này có nghĩa là khi thực hiện các thao tác chèn và cập nhật trên dữ liệu, SQL Server phải thực hiện một số lượng lớn các thao tác tiêu tốn nhiều tài nguyên để chia trang và di chuyển một phần của trang hiện có sang vị trí mới. Những hoạt động như vậy nên tránh bất cứ khi nào có thể. Bạn có thể cố gắng giải quyết vấn đề theo hai cách:
      - tạo chỉ mục nhóm cho các cột tăng tự động. Trong trường hợp này, các bản ghi mới sẽ không được đặt bên trong các trang đã chứa dữ liệu mà sẽ lần lượt chiếm các trang mới;
      — xây dựng lại các chỉ mục bằng cách tăng giá trị của tham số Fillfactor. Tùy chọn này cho phép bạn dự trữ không gian trống trong các trang chỉ mục sẽ được sử dụng để chứa dữ liệu mới mà không cần thao tác chia trang.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Phương thức truy cậpChia trang/giây",30] Ví dụ kích hoạt: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Phương thức truy cậpChia trang/giây",30].last()}>{NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Số yêu cầu hàng loạt thống kê SQL/giây",30].last()} /5, thông tin cấp độ
    2. Quét toàn bộ/giây
      Không giới hạn số lần quét toàn bộ mỗi giây. Các hoạt động này bao gồm quét bảng chính và quét chỉ mục đầy đủ. Chỉ số này tăng ổn định có thể cho thấy sự xuống cấp của hệ thống (thiếu các chỉ mục cần thiết, sự phân mảnh nghiêm trọng của chúng, trình tối ưu hóa không thể sử dụng các chỉ mục hiện có, sự hiện diện của các chỉ mục không được sử dụng). Tuy nhiên, điều đáng chú ý là việc quét toàn bộ trong các bảng nhỏ không phải lúc nào cũng xấu, vì nếu bạn có thể đặt toàn bộ bảng vào RAM thì việc quét toàn bộ sẽ nhanh hơn. Nhưng trong hầu hết các trường hợp, mức tăng ổn định của bộ đếm này sẽ cho thấy sự xuống cấp của hệ thống. Tất cả điều này chỉ áp dụng cho các hệ thống OLTP. Trong hệ thống OLAP, việc quét toàn bộ liên tục là bình thường.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Phương thức truy cậpQuét toàn bộ/giây",30]

  6. Máy chủ MS SQL: Trình quản lý bộ đệm
    Đối tượng Trình quản lý bộ đệm cung cấp các bộ đếm giúp bạn theo dõi cách SQL Server sử dụng các tài nguyên sau:
    - bộ nhớ để lưu trữ các trang dữ liệu;
    - bộ đếm giám sát I/O vật lý khi SQL Server đọc và ghi các trang cơ sở dữ liệu;
    — mở rộng vùng đệm để mở rộng bộ đệm đệm bằng cách sử dụng bộ nhớ ổn định nhanh, chẳng hạn như ổ đĩa thể rắn (SSD);
    - Giám sát bộ nhớ và bộ đếm được SQL Server sử dụng giúp thu được các thông tin sau;
    — liệu có tắc nghẽn do thiếu bộ nhớ vật lý hay không. Nếu dữ liệu được truy cập thường xuyên không thể được lưu trữ trong bộ đệm, SQL Server buộc phải đọc dữ liệu đó từ đĩa;
    Có thể cải thiện hiệu suất truy vấn bằng cách tăng dung lượng bộ nhớ hoặc phân bổ bộ nhớ bổ sung để lưu trữ dữ liệu hoặc lưu trữ cấu trúc SQL Server nội bộ không?
    — tần suất SQL Server đọc dữ liệu từ đĩa. So với các hoạt động khác như truy cập bộ nhớ, I/O vật lý mất nhiều thời gian hơn để hoàn thành. Giảm I/O có thể cải thiện hiệu suất truy vấn.

    1. Đài phát thanh Buffer Cache
      Cho biết lượng dữ liệu SQL Server có thể vừa với bộ đệm bộ đệm. Giá trị này càng cao thì càng tốt vì Để SQL Server truy cập hiệu quả các trang dữ liệu, chúng phải nằm trong bộ đệm đệm và không được có thao tác đầu vào/đầu ra (I/O) vật lý nào. Nếu bạn thấy giá trị trung bình của bộ đếm này giảm đều đặn thì bạn nên cân nhắc việc bổ sung thêm RAM. Chỉ báo này phải luôn ở mức trên 90% đối với hệ thống OLTP và trên 50% đối với hệ thống OLAP.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Tỷ lệ truy cập bộ đệm bộ đệm của Trình quản lý bộ đệm",30] Ví dụ kích hoạt: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Tỷ lệ nhấn bộ đệm bộ đệm của Trình quản lý bộ đệm",30].last()<70, cấp cao
      и
      {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Tỷ lệ nhấn bộ nhớ đệm của Trình quản lý bộ đệm",30].last()<80, cấp độ trung bình
    2. Tuổi thọ của trang
      Hiển thị thời gian trang sẽ tồn tại vĩnh viễn trong bộ nhớ ở trạng thái hiện tại. Nếu giá trị tiếp tục giảm, điều đó có nghĩa là hệ thống đang lạm dụng vùng đệm. Do đó, hiệu suất bộ nhớ có thể gây ra sự cố dẫn đến hiệu suất kém. Điều đáng chú ý là không có chỉ báo chung nào dưới đây mà người ta có thể đánh giá rõ ràng rằng hệ thống đang lạm dụng vùng đệm (chỉ báo 300 giây đã lỗi thời kể từ MS SQL Server 2012).
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Tuổi thọ của trang Trình quản lý bộ đệm",30] Ví dụ kích hoạt: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Tuổi thọ của trang Trình quản lý bộ đệm",30].last()<5, thông tin cấp độ

  7. Máy chủ MS SQL: Thống kê chung
    Đối tượng Thống kê chung trong SQL Server cung cấp các bộ đếm cho phép bạn giám sát hoạt động tổng thể của máy chủ, chẳng hạn như số lượng kết nối đồng thời và số lượng người dùng mỗi giây kết nối đến hoặc ngắt kết nối khỏi máy tính chạy phiên bản SQL Server. Các số liệu này rất hữu ích trong các hệ thống xử lý giao dịch trực tuyến (OLTP) lớn, nơi có một số lượng lớn máy khách liên tục kết nối và ngắt kết nối khỏi phiên bản SQL Server.

    1. Quá trình bị chặn
      Số lượng tiến trình hiện đang bị chặn.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Thống kê chungQuy trình bị chặn",30] Ví dụ kích hoạt: ({NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Quy trình thống kê chung bị chặn",30].min(2m,0)}>=0)
      và ({NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Quy trình thống kê chung bị chặn",30].time(0)}>=50000)
      và ({NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:General StatisticProcesses bị chặn",30].time(0)</=230000), mức thông tin (ở đây có hạn chế báo hiệu từ 05:00 đến 23:00)
    2. Kết nối người dùng
      Số lượng người dùng hiện đang kết nối với SQL Server.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Thống kê chungKết nối người dùng",30]

  8. Máy chủ MS SQL: Khóa
    Đối tượng Khóa trong Microsoft SQL Server cung cấp thông tin về các khóa SQL Server có được cho các loại tài nguyên riêng lẻ. Khóa được cấp trên tài nguyên SQL Server, chẳng hạn như các hàng được đọc hoặc sửa đổi bởi một giao dịch, để ngăn nhiều giao dịch sử dụng tài nguyên cùng một lúc. Ví dụ: nếu một giao dịch trên một hàng trong bảng có được khóa (X) độc quyền thì không giao dịch nào khác có thể thay đổi hàng đó cho đến khi khóa được giải phóng. Giảm thiểu việc sử dụng khóa sẽ tăng tính đồng thời, có thể cải thiện hiệu suất tổng thể. Một số phiên bản của đối tượng Khóa có thể được theo dõi cùng lúc, mỗi phiên bản sẽ đại diện cho một khóa trên một loại tài nguyên riêng biệt.

    1. Thời gian chờ trung bình (ms)
      Thời gian chờ trung bình (tính bằng mili giây) cho tất cả các yêu cầu khóa yêu cầu chờ. Bộ đếm này cho biết trung bình các tiến trình của người dùng phải đợi trong hàng đợi bao lâu để có được khóa trên tài nguyên. Giá trị tối đa cho phép của bộ đếm này hoàn toàn phụ thuộc vào nhiệm vụ của bạn; rất khó để xác định bất kỳ giá trị trung bình nào cho tất cả các ứng dụng. Nếu bộ đếm này quá cao, nó có thể cho thấy có vấn đề về khóa trong cơ sở dữ liệu của bạn.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Thời gian chờ trung bình (ms)",30] Ví dụ kích hoạt: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Thời gian chờ trung bình (ms)",30].last()}>=500, thông tin cấp độ
    2. Thời gian chờ khóa (ms)
      Tổng thời gian chờ khóa (tính bằng mili giây) trong giây cuối cùng.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Thời gian chờ khóa (ms)",30]
    3. Khóa chờ/giây
      Số lần trong giây cuối cùng mà một luồng phải chờ do yêu cầu khóa.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Waits/sec",30]
    4. Khóa thời gian chờ/giây
      Số lần mà khóa không thể lấy được bằng cách quay vòng. Giá trị tham số cấu hình bộ đếm vòng quay của SQL Server xác định số lần một luồng có thể quay trước khi hết thời gian và luồng trở nên không hoạt động.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Timeouts/sec",30] Ví dụ kích hoạt: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Locks(_Total)Lock Timeouts/sec",30].last()}>1000, thông tin cấp độ
    5. Yêu cầu khóa/giây
      Số lượng yêu cầu mỗi giây của loại khóa được chỉ định.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Yêu cầu/giây",30] Ví dụ kích hoạt: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Locks(_Total)Lock Yêu cầu/giây",30].last()}>500000, thông tin cấp độ
    6. Khóa số lần bế tắc/giây
      Số lượng yêu cầu khóa mỗi giây dẫn đến bế tắc. Sự hiện diện của bế tắc cho thấy các truy vấn được xây dựng kém đang chặn tài nguyên được chia sẻ.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Số lần bế tắc/giây",30] Ví dụ kích hoạt: {NODE_NAME:perf_counter["MSSQL$INSTANCE_NAME:Khóa(_Total)Số lần bế tắc/giây",30].last()}>1, cấp cao

  9. Máy chủ MS SQL: Trình quản lý bộ nhớ
    Đối tượng Trình quản lý bộ nhớ trong Microsoft SQL Server cung cấp bộ đếm để giám sát việc sử dụng bộ nhớ trên toàn máy chủ. Giám sát việc sử dụng bộ nhớ của toàn bộ máy chủ để đánh giá hoạt động của người dùng và việc sử dụng tài nguyên có thể giúp xác định các tắc nghẽn về hiệu suất. Việc giám sát bộ nhớ được phiên bản SQL Server sử dụng có thể giúp xác định:
    — liệu có thiếu bộ nhớ vật lý đủ để lưu trữ dữ liệu được sử dụng thường xuyên trong bộ đệm hay không. Nếu không đủ bộ nhớ, SQL Server phải lấy dữ liệu từ đĩa;
    - Liệu hiệu suất truy vấn có thể cải thiện nếu bộ nhớ được thêm vào hay lượng bộ nhớ khả dụng cho dữ liệu bộ nhớ đệm hoặc cấu trúc SQL Server nội bộ được tăng lên.

    1. Tài trợ bộ nhớ xuất sắc
      Cho biết tổng số quy trình đã giành được bộ nhớ không gian làm việc thành công. Nếu chỉ báo giảm đều thì cần phải tăng RAM.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Trình quản lý bộ nhớCấp bộ nhớ xuất sắc",30]
    2. Cấp bộ nhớ đang chờ xử lý
      Cho biết tổng số tiến trình đang chờ bộ nhớ làm việc được cấp phát. Với sự tăng trưởng ổn định của chỉ số, việc tăng RAM là cần thiết.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Trình quản lý bộ nhớCấp bộ nhớ đang chờ xử lý",30]

  10. Máy chủ MS SQL: Thống kê
    Đối tượng Thống kê trong Microsoft SQL Server cung cấp các bộ đếm để giám sát quá trình biên dịch và các loại truy vấn được gửi đến một phiên bản của SQL Server. Việc giám sát số lượng biên dịch và biên dịch lại truy vấn cũng như số lô mà một phiên bản SQL Server nhận được sẽ cung cấp thông tin chi tiết về tốc độ SQL Server thực thi các truy vấn của người dùng cũng như mức độ hiệu quả mà trình tối ưu hóa truy vấn xử lý chúng.

    1. Yêu cầu hàng loạt / giây
      Số lượng gói lệnh Transact-SQL nhận được mỗi giây. Những thống kê này bị ảnh hưởng bởi bất kỳ giới hạn nào (I/O, số lượng người dùng, kích thước bộ đệm, độ phức tạp của truy vấn, v.v.). Số lượng yêu cầu gói cao cho thấy thông lượng cao.
      Zabbix: perf_counter["MSSQL$INSTANCE_NAME:Số yêu cầu hàng loạt thống kê SQL/giây",30]

Ngoài tất cả những điều trên, bạn cũng có thể định cấu hình các thành phần dữ liệu khác (cũng như tạo trình kích hoạt trên chúng bằng các thông báo tiếp theo). Ví dụ:
1) dung lượng đĩa trống
2) kích thước của tệp dữ liệu cơ sở dữ liệu và nhật ký
d và t..
Tuy nhiên, tất cả các chỉ số này không cho thấy vấn đề về truy vấn thời gian thực.
Để làm điều này, bạn cần tạo các bộ đếm đặc biệt của riêng mình.
Vì lý do bảo mật, tôi sẽ không đưa ra ví dụ về các máy đếm như vậy. Hơn nữa, chúng được cấu hình riêng cho từng hệ thống. Nhưng tôi lưu ý rằng đối với các hệ thống như 1C, NAV và CRM, các bộ đếm chuyên dụng có thể được tạo cùng với các nhà phát triển có liên quan.
Tôi sẽ đưa ra một ví dụ về việc tạo một chỉ báo tổng quát cho biết có bao nhiêu yêu cầu đang chạy và bao nhiêu yêu cầu đang chờ xử lý (bị treo hoặc bị chặn) tại mỗi thời điểm.
Để thực hiện việc này, bạn cần tạo một thủ tục lưu trữ:

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

Tiếp theo, bạn cần đi đến thư mục chứa Zabbix (zabbixconfuserparams.d) và tạo 2 tệp có phần mở rộng ps1 (PowerShell) và viết các mã sau vào mỗi tệp:
Mã để chạy truy vấn

$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;

Mã cho các yêu cầu đang chờ xử lý

$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;

Bây giờ bạn cần tạo một tệp có tham số người dùng và phần mở rộng .conf (hoặc thêm dòng vào tệp người dùng hiện có, nếu tệp đã được tạo trước đó) và chèn các dòng sau:
UserParameter=PARAMETER_NAME_NUMBER_of_QUERIES EXECUTED,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILE_NAME_FOR_EXECUTION_QUERYES.ps1
UserParameter=PARAMETER_NAME_NUMBER_WAITING_REQUESTS,powershell -NoProfile -ExecutionPolicy Bypass -File FULL_PATHzabbixconfuserparams.dFILE_NAME_FOR_WAITING_REQUESTS.ps1
Sau đó, lưu tệp .conf và khởi động lại tác nhân Zabbix.
Sau đó, chúng tôi thêm hai phần tử mới vào Zabbix (trong trường hợp này, tên và khóa giống nhau):
PARAMETER_NAME_NUMBER OF_REQUESTS ĐƯỢC THỰC HIỆN
PARAMETER_NAME_NUMBER OF_WAITING_REQUESTS
Bây giờ bạn có thể tạo biểu đồ và trình kích hoạt cho các mục dữ liệu tùy chỉnh đã tạo.

Nếu số lượng yêu cầu đang chờ xử lý tăng mạnh thì truy vấn sau có thể hiển thị tất cả các yêu cầu đang chạy và đang chờ xử lý tại một thời điểm nhất định với thông tin chi tiết về vị trí và theo thông tin đăng nhập mà yêu cầu được thực thi, văn bản và kế hoạch truy vấn cũng như các chi tiết khác:

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

Tôi cũng xin nhắc bạn rằng theo số liệu thống kê được thu thập, bạn có thể nhận được những truy vấn khó nhất:

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

Bạn cũng có thể viết cho MySQL. Để làm được điều này bạn cần cài đặt mysql-kết nối-net và sau đó viết mã như thế này:
Mã cho các yêu cầu đang chờ xử lý

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

Kết quả

Bài viết này xem xét một ví dụ về bộ đếm hiệu suất (mục dữ liệu) trong Zabbix. Cách tiếp cận này cho phép quản trị viên được thông báo về các vấn đề khác nhau trong thời gian thực hoặc sau một thời gian cụ thể. Do đó, cách tiếp cận này cho phép chúng tôi giảm thiểu khả năng xảy ra sự cố nghiêm trọng trong tương lai và dừng hoạt động của DBMS và máy chủ, từ đó bảo vệ quá trình sản xuất không bị dừng quá trình làm việc.
bài báo trước: Làm việc thường xuyên với cơ sở dữ liệu hệ thống thông tin 24×7 trong MS SQL Server

Nguồn:

» Zabbix 3.4
» Bộ đếm hiệu suất
» Trung tâm hiệu suất cho cơ sở dữ liệu Azure SQL và công cụ cơ sở dữ liệu SQL Server
» Lối sống SQL
» Kỹ năng SQL
» TechNet Microsoft
» Phân tích việc sử dụng bộ nhớ
» Phân tích hiệu suất
» Tài liệu SQL
» Ghi chú về Windows

Nguồn: www.habr.com

Thêm một lời nhận xét