Đây có phải là một triệu chứng của một máy chủ quá tải?


12

Tôi đã cố gắng chẩn đoán sự chậm chạp trong một ứng dụng. Đối với điều này, tôi đã đăng nhập các sự kiện mở rộng của SQL Server .

  • Đối với câu hỏi này, tôi đang xem xét một thủ tục được lưu trữ cụ thể.
  • Nhưng có một tập hợp cốt lõi của một tá các thủ tục được lưu trữ có thể được sử dụng như một cuộc điều tra táo với táo
  • và bất cứ khi nào tôi tự chạy một trong các thủ tục được lưu trữ, nó luôn chạy nhanh
  • và nếu người dùng thử lại: nó sẽ chạy nhanh.

Thời gian thực hiện của thủ tục được lưu trữ rất khác nhau. Rất nhiều thực thi của thủ tục được lưu trữ này trả về trong <1s:

nhập mô tả hình ảnh ở đây

Và đối với cái xô "nhanh" đó, nó ít hơn 1 giây. Nó thực sự khoảng 90 ms:

nhập mô tả hình ảnh ở đây

Nhưng có một cái đuôi dài của người dùng phải chờ 2 giây, 3 giây, 4 giây. Một số phải chờ 12, 13, 14. Sau đó, có những linh hồn thực sự đáng thương, những người phải chờ 22, 23, 24.

Và sau 30 giây, ứng dụng khách bỏ cuộc, hủy bỏ truy vấn và người dùng phải đợi 30 giây .

Tương quan để tìm nhân quả

Vì vậy, tôi đã cố gắng để tương quan:

  • thời lượng so với đọc hợp lý
  • thời lượng so với đọc vật lý
  • thời lượng so với thời gian cpu

Và dường như không có bất kỳ mối tương quan nào; dường như không có nguyên nhân

  • thời lượng so với số lần đọc logic : dù là một ít hay nhiều lần đọc logic, thời lượng vẫn dao động dữ dội :

    nhập mô tả hình ảnh ở đây

  • thời lượng so với đọc vật lý : ngay cả khi truy vấn không được cung cấp từ bộ đệm và rất nhiều lần đọc vật lý là cần thiết, nó không ảnh hưởng đến thời lượng:

    nhập mô tả hình ảnh ở đây

  • thời lượng so với thời gian cpu : Cho dù truy vấn mất 0 giây thời gian CPU hay 2,5 giây thời gian CPU đầy đủ, thời lượng có cùng một biến thiên:

    nhập mô tả hình ảnh ở đây

Phần thưởng : Tôi nhận thấy rằng Thời lượng v Vật lý đọcThời lượng v Thời gian CPU trông rất giống nhau. Điều này được chứng minh nếu tôi cố gắng tương quan thời gian của CPU với Đọc vật lý:

nhập mô tả hình ảnh ở đây

Hóa ra rất nhiều việc sử dụng CPU đến từ I / O. Ai biết!

Vì vậy, nếu không có gì về hành động thực hiện truy vấn có thể giải thích cho sự khác biệt về thời gian thực hiện, thì điều đó có nghĩa là đó là một cái gì đó không liên quan đến CPU hoặc ổ cứng?

Nếu CPU hoặc ổ cứng là nút cổ chai; nó sẽ không phải là nút cổ chai?

Nếu chúng ta đưa ra giả thuyết rằng đó là CPU là nút cổ chai; CPU được cung cấp năng lượng cho máy chủ này:

  • Sau đó, việc thực thi sử dụng nhiều thời gian CPU sẽ mất nhiều thời gian hơn?
  • vì họ phải hoàn thành với những người khác sử dụng CPU quá tải?

Tương tự cho các ổ đĩa cứng. Nếu chúng ta đưa ra giả thuyết rằng ổ cứng là một nút cổ chai; rằng các ổ đĩa cứng không có đủ thông qua ngẫu nhiên cho máy chủ này:

  • sau đó sẽ không thực hiện bằng cách sử dụng đọc vật lý nhiều hơn mất nhiều thời gian?
  • vì họ phải hoàn thành với những người khác bằng cách sử dụng I / O ổ cứng quá tải?

Các thủ tục được lưu trữ tự nó không thực hiện, cũng không yêu cầu, bất kỳ ghi.

  • Thông thường nó trả về 0 hàng (90%).
  • Thỉnh thoảng nó sẽ trả về 1 hàng (7%).
  • Hiếm khi nó sẽ trả về 2 hàng (1,4%).
  • Và trong trường hợp xấu nhất, nó đã trả về hơn 2 hàng (một lần trả lại 12 hàng)

Vì vậy, nó không giống như nó trả lại một khối lượng dữ liệu điên rồ.

Sử dụng CPU máy chủ

Mức sử dụng bộ xử lý của máy chủ trung bình khoảng 1,8%, với mức tăng đột biến lên tới 18% - vì vậy có vẻ như tải CPU là một vấn đề:

nhập mô tả hình ảnh ở đây

Vì vậy, CPU máy chủ dường như không bị quá tải.

Nhưng máy chủ ảo ...

Một cái gì đó bên ngoài vũ trụ?

Điều duy nhất còn lại tôi có thể tưởng tượng là thứ gì đó tồn tại bên ngoài vũ trụ của máy chủ.

  • nếu nó không hợp lý đọc
  • và nó không phải là đọc vật lý
  • và nó không sử dụng cpu
  • và nó không tải CPU

Và nó không giống như các tham số cho thủ tục được lưu trữ (vì đưa ra cùng một truy vấn theo cách thủ công và không mất 27 giây - mất ~ 0 giây).

Những gì khác có thể chiếm cho máy chủ đôi khi mất 30 giây, thay vì 0 giây, để chạy cùng một quy trình được lưu trữ được biên dịch.

  • trạm kiểm soát?

Nó là một máy chủ ảo

  • Máy chủ quá tải?
  • VM khác trên cùng một máy chủ?

Đi qua các sự kiện mở rộng của máy chủ; không có gì khác đặc biệt xảy ra khi một truy vấn đột nhiên mất 20 giây. Nó chạy tốt, sau đó quyết định không chạy tốt:

  • 2 giây
  • 1 giây
  • 30 giây
  • 3 giây
  • 2 giây

Và không có vật phẩm vất vả nào khác tôi có thể tìm thấy. Đó không phải là trong mỗi bản sao lưu nhật ký giao dịch 2 giờ.

có thể là gì khác?

Có điều gì tôi có thể nói ngoài: "máy chủ" không?

Chỉnh sửa : Tương quan theo thời gian trong ngày

Tôi nhận ra tôi đã tương quan thời lượng với mọi thứ:

  • đọc logic
  • đọc vật lý
  • sử dụng CPU

Nhưng điều duy nhất tôi không liên quan đến nó là thời gian trong ngày . Có lẽ sao lưu nhật ký giao dịch cứ sau 2 giờ một vấn đề.

Hoặc có lẽ là chậm làm xảy ra trong các ngăn trong trạm kiểm soát?

Không

nhập mô tả hình ảnh ở đây

Intel Xeon Gold Quad-core 6142.

Chỉnh sửa - Mọi người đang giả định kế hoạch thực hiện truy vấn

Mọi người đang đưa ra giả thuyết về kế hoạch thực hiện truy vấn phải khác nhau giữa "nhanh" và "chậm". Họ không phải.

Và chúng ta có thể thấy điều này ngay lập tức từ kiểm tra.

Chúng tôi biết thời lượng câu hỏi dài hơn không phải vì kế hoạch thực hiện "kém":

  • một bài đọc hợp lý hơn
  • một CPU tiêu thụ nhiều CPU hơn từ nhiều lần tham gia và tra cứu khóa

Bởi vì nếu việc tăng đọc hoặc tăng CPU là nguyên nhân của thời lượng truy vấn tăng lên, thì chúng ta đã thấy điều đó ở trên. Không có mối tương quan.

Nhưng hãy thử tương quan thời lượng với chỉ số sản phẩm của khu vực đọc CPU:

nhập mô tả hình ảnh ở đây

Thậm chí còn trở nên ít hơn về một mối tương quan - đó là một nghịch lý.


Chỉnh sửa : Đã cập nhật sơ đồ phân tán để khắc phục lỗi trong các biểu đồ phân tán Excel với số lượng lớn các giá trị.

Bước tiếp theo

Các bước tiếp theo của tôi sẽ là khiến ai đó phải tạo máy chủ để tạo các sự kiện cho các truy vấn bị chặn - sau 5 giây:

EXEC sp_configure 'blocked process threshold', '5';
RECONFIGURE

Nó sẽ không giải thích nếu các truy vấn bị chặn trong 4 giây. Nhưng có lẽ bất cứ điều gì chặn truy vấn trong 5 giây cũng chặn một số trong 4 giây.

Máy quay chậm

Đây là kế hoạch chậm của hai thủ tục được lưu trữ đang được thực thi:

  • `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'
  • `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'

Quy trình được lưu trữ tương tự, với cùng các tham số, chạy ngược lại:

| Duration (us) | CPU time (us) | Logical reads | Physical reads | 
|---------------|---------------|---------------|----------------|
|    13,984,446 |        47,000 |         5,110 |            771 |
|     4,603,566 |        47,000 |         5,126 |            740 |

Gọi 1:

|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
    |    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]),  WHERE:([Contos
    |--Filter(WHERE:([Expr1009]>(1)))
     |--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
          |--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
           |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC

Gọi 2

|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
    |    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]),  WHERE:([Contos
    |--Filter(WHERE:([Expr1009]>(1)))
     |--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
          |--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
           |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC

Nó có ý nghĩa cho các kế hoạch là giống hệt nhau; nó đang thực hiện cùng một thủ tục được lưu trữ, với cùng các tham số.


2
Bạn có thể đăng các kế hoạch truy vấn - chạy tốt và chạy xấu?
Kin Shah

4
Dự đoán đầu tiên của tôi từ đây sẽ bị chặn ...
Tibor Karaszi

3
Ai đã đánh giá thấp điều này? Đó là một câu hỏi rất được nghiên cứu kỹ lưỡng, mặc dù nó thiếu các kế hoạch truy vấn! +1 từ tôi!
Vérace

4
Làm thế nào bạn đi đến kết luận rằng các kế hoạch truy vấn là "giống hệt nhau"? Bạn chỉ có nghĩa là họ có hình dạng giống nhau? Đăng chúng ở đâu đó để chúng ta có thể so sánh quá. Chỉ cần nói với chúng tôi rằng chúng giống hệt nhau không có nghĩa là chúng giống hệt nhau.
Aaron Bertrand

3
Việc thêm các kế hoạch thực hiện chính thức bằng PasteThePlan có thể cho chúng ta biết ý tưởng của truy vấn đang chờ đợi.
Randi Vertongen

Câu trả lời:


2

Hãy xem Wait_stats và nó sẽ hiển thị những điểm nghẽn lớn nhất trên máy chủ SQL của bạn.

Gần đây tôi đã gặp một vấn đề trong đó một ứng dụng bên ngoài bị gián đoạn chậm. Chạy các thủ tục được lưu trữ trên máy chủ luôn luôn nhanh.

Giám sát hiệu suất cho thấy không có gì phải lo lắng với SQL Caches hoặc việc sử dụng RAM và IO trên máy chủ.

Điều giúp thu hẹp cuộc điều tra là truy vấn các số liệu thống kê chờ được SQL thu thập trong sys.dm_os_wait_stats

Kịch bản tuyệt vời trên trang web SQLSkills sẽ cho bạn thấy những kịch bản bạn đang trải nghiệm nhất. Sau đó, bạn có thể thu hẹp tìm kiếm của bạn để xác định nguyên nhân.

Khi bạn biết điều gì đang chờ đợi là vấn đề lớn, tập lệnh này sẽ giúp thu hẹp phiên / cơ sở dữ liệu nào đang gặp phải sự chờ đợi:

SELECT OSW.session_id,
       OSW.wait_duration_ms,
       OSW.wait_type,
       DB_NAME(EXR.database_id) AS DatabaseName
FROM sys.dm_os_waiting_tasks OSW
INNER JOIN sys.dm_exec_sessions EXS ON OSW.session_id = EXS.session_id
INNER JOIN sys.dm_exec_requests EXR ON EXR.session_id = OSW.session_id
OPTION(Recompile);

Truy vấn trên và chi tiết hơn là từ trang web MSSQLTips .

Các sp_BlitzFirstkịch bản từ Brent Ozar của trang web cũng sẽ cho bạn thấy những gì đang gây ra chậm trễ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.