Khi một truy vấn SQL nhanh trước đó bắt đầu chạy chậm, tôi phải tìm nguồn gốc của vấn đề ở đâu?


36

Lý lịch

Tôi có một truy vấn chạy với SQL Server 2008 R2 tham gia và / hoặc tham gia trái khoảng 12 "bảng" khác nhau. Cơ sở dữ liệu khá lớn với nhiều bảng trên 50 triệu hàng và khoảng 300 bảng khác nhau. Đó là cho một công ty lớn có 10 kho trên toàn quốc. Tất cả các kho đọc và ghi vào cơ sở dữ liệu. Vì vậy, nó khá lớn và khá bận rộn.

Truy vấn tôi gặp rắc rối với giao diện giống như thế này:

select t1.something, t2.something, etc.
from Table1 t1
    inner join Table2 t2 on t1.id = t2.t1id
    left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
    [etc]...
where t1.something = 123

Lưu ý rằng một trong các phép nối nằm trên truy vấn con không tương quan.

Vấn đề là bắt đầu từ sáng nay, không có bất kỳ thay đổi nào (mà tôi hoặc bất kỳ ai trong nhóm của tôi biết) đối với hệ thống, truy vấn thường mất khoảng 2 phút để chạy, bắt đầu mất một tiếng rưỡi để chạy - khi nó chạy chạy hết rồi. Phần còn lại của cơ sở dữ liệu là tốt. Tôi đã đưa truy vấn này ra khỏi chuỗi mà nó thường chạy và tôi đã chạy nó trong SSMS với các biến tham số được mã hóa cứng với cùng độ chậm.

Điều kỳ lạ là khi tôi lấy truy vấn phụ không tương quan và ném nó vào bảng tạm thời, sau đó sử dụng truy vấn đó thay cho truy vấn phụ, truy vấn sẽ chạy tốt. Ngoài ra (và đây là điều kỳ lạ nhất đối với tôi) nếu tôi thêm đoạn mã này vào cuối truy vấn, truy vấn sẽ chạy rất tốt:

and t.name like '%'

Tôi đã kết luận (có lẽ không chính xác) từ những thử nghiệm nhỏ này rằng lý do chậm lại là do cách thiết lập kế hoạch thực thi được lưu trong bộ nhớ cache của SQL - khi truy vấn hơi khác một chút, nó phải tạo một kế hoạch thực hiện mới.

Câu hỏi của tôi là: Khi một truy vấn được sử dụng để chạy nhanh đột nhiên bắt đầu chạy chậm vào giữa đêm và không có gì khác bị ảnh hưởng ngoại trừ một truy vấn này, làm cách nào để khắc phục sự cố này và làm thế nào để tôi không xảy ra trong tương lai ? Làm cách nào để biết SQL đang làm gì bên trong để làm cho nó chậm như vậy (nếu truy vấn xấu chạy, tôi có thể nhận được kế hoạch thực hiện nhưng nó sẽ không chạy - có lẽ kế hoạch thực hiện dự kiến ​​sẽ cung cấp cho tôi thứ gì đó?)? Nếu vấn đề này xảy ra với kế hoạch thực hiện, làm cách nào để SQL không nghĩ rằng các kế hoạch thực hiện thực sự nhảm nhí là một ý tưởng tốt?

Ngoài ra, đây không phải là một vấn đề với việc đánh hơi tham số. Tôi đã thấy điều đó trước đây, và đây không phải là nó, vì ngay cả khi tôi mã hóa các biến đổi trong SSMS, tôi vẫn nhận được hiệu suất chậm.


Bạn có thể chia sẻ kế hoạch truy vấn (chậm không) tại đây: brentozar.com/pastetheplan
MJH

Câu trả lời:


31

Khi một truy vấn được sử dụng để chạy nhanh đột nhiên bắt đầu chạy chậm vào giữa đêm và không có gì khác bị ảnh hưởng ngoại trừ một truy vấn này, làm cách nào để khắc phục sự cố đó ...?

Bạn có thể bắt đầu bằng cách kiểm tra xem kế hoạch thực hiện có còn trong bộ đệm không. Kiểm tra sys.dm_exec_query_stats, sys.dm_exec_procedure_statssys.dm_exec_cached_plans. Nếu kế hoạch thực hiện xấu vẫn được lưu trong bộ nhớ cache, bạn có thể phân tích nó và bạn cũng có thể kiểm tra số liệu thống kê thực hiện. Các thống kê thực hiện sẽ chứa thông tin dưới dạng đọc logic, thời gian CPU và thời gian thực hiện. Chúng có thể cho biết dấu hiệu của vấn đề là gì (ví dụ: quét lớn so với chặn). Xem Xác định các truy vấn vấn đề để biết giải thích cách diễn giải dữ liệu.

Ngoài ra, đây không phải là một vấn đề với việc đánh hơi tham số. Tôi đã thấy điều đó trước đây, và đây không phải là nó, vì ngay cả khi tôi mã hóa các biến đổi trong SSMS, tôi vẫn nhận được hiệu suất chậm.

Tôi không tin chắc. Các biến mã hóa cứng trong SSMS không chứng minh rằng kế hoạch thực hiện xấu trong quá khứ không được biên dịch theo đầu vào sai lệch. Vui lòng đọc Thông số Đánh hơi, Nhúng và Tùy chọn RECOMPILE cho một bài viết rất hay về chủ đề này. Chậm trong ứng dụng, nhanh trong SSMS? Hiểu bí ẩn hiệu suất là một tài liệu tham khảo tuyệt vời khác.

Tôi đã kết luận (có lẽ không chính xác) từ những thử nghiệm nhỏ này rằng lý do chậm lại là do cách thiết lập kế hoạch thực thi được lưu trong bộ nhớ cache của SQL - khi truy vấn hơi khác một chút, nó phải tạo một kế hoạch thực hiện mới.

Điều này có thể dễ dàng kiểm tra. SET STATISTICS TIME ONsẽ cho bạn thấy thời gian biên dịch so với thời gian thực hiện. SQL Server: Bộ đếm hiệu suất thống kê cũng sẽ tiết lộ liệu việc biên dịch có phải là một vấn đề hay không (thẳng thắn, tôi thấy nó không có khả năng).

Tuy nhiên, có một thứ tương tự mà bạn có thể nhấn: cổng cấp truy vấn. Đọc Hiểu cấp bộ nhớ máy chủ SQL để biết chi tiết. Nếu truy vấn của bạn yêu cầu một khoản trợ cấp lớn tại một thời điểm không có bộ nhớ, nó sẽ phải chờ và tất cả sẽ trông giống như 'thực thi chậm' cho ứng dụng. Phân tích thống kê thông tin chờ đợi sẽ tiết lộ nếu đây là trường hợp.

Để thảo luận tổng quát hơn về những gì cần đo và những gì cần tìm, hãy xem Cách phân tích hiệu suất của SQL Server


7

Đây là một nguyên nhân của việc chạy các truy vấn phức tạp trong SQL Server. May mắn thay, điều đó không xảy ra thường xuyên.

Nhìn vào kế hoạch truy vấn cho truy vấn (khi nó đang chạy chậm). Tôi đoán bạn sẽ tìm thấy một phép nối vòng lặp lồng nhau xảy ra một hoặc nhiều lần trên các bảng không có chỉ mục cho phép nối. Điều này thực sự làm mọi thứ chậm lại. Để nhanh chóng chuyển tiếp, cách để khắc phục điều này là với một gợi ý. Thêm phần sau vào cuối truy vấn:

OPTION (MERGE JOIN, HASH JOIN)

Điều này nói chung đã khắc phục vấn đề này cho tôi trong quá khứ.

Điều có thể xảy ra là những thay đổi tinh tế đối với bảng (hoặc tính khả dụng của không gian tạm thời) khiến tối ưu hóa SQL thích thuật toán nối chậm hơn. Điều này có thể khá tinh tế và khá đột ngột. Khi bạn tạo một bảng tạm thời, trình tối ưu hóa có thêm thông tin về bảng (chẳng hạn như kích thước của nó), do đó nó có thể tạo ra một kế hoạch tốt hơn.


1
Kế hoạch thực hiện thực sự là sử dụng một phép nối vòng lặp lồng nhau. Tuy nhiên, khi tôi đặt gợi ý như bạn đề xuất, tôi gặp lỗi này: "Bộ xử lý truy vấn không thể tạo kế hoạch truy vấn do các gợi ý được xác định trong truy vấn này. Gửi lại truy vấn mà không chỉ định bất kỳ gợi ý nào và không sử dụng SET FORCEPlan." Khi tôi thêm TÙY CHỌN (LOOP THAM GIA), nó sẽ tạo ra một kế hoạch thực hiện nhưng tôi vẫn gặp vấn đề với nó chạy chậm. Bạn đã gặp phải vấn đề này? Có vẻ như nó nghĩ rằng nó CẦN phải lặp lại tham gia.

@Trevor. . . Không, tôi chưa thực sự thấy vấn đề này. Có lẽ truy vấn của bạn đang thực hiện một số phi đẳng thức (không sử dụng các dấu bằng) và trình tối ưu hóa phải sử dụng các vòng lặp lồng nhau tham gia ở đó.
Gordon Linoff

3

Thông thường đó là một chỉ số bị thiếu gây ra loại vấn đề này.

Những gì tôi thường làm là chạy truy vấn bằng SQL Management Studio và bật 'Bao gồm Kế hoạch thực thi thực tế (CTRL + M)' và tìm hiểu xem tham gia nào có tỷ lệ phần trăm lớn nhất.

Ứng dụng không tập trung vào nút cổ chai, nhưng bạn có thể thấy nó "nhanh chóng" chỉ nhìn vào kết quả.

ví dụ ở đây: 48PercentForTop


2
một chỉ số sẽ không đột nhiên "mất tích", vì vậy trong khi điều này có thể cải thiện hiệu suất thì nó không giải thích được vấn đề
Fowl

3

Gần đây tôi đã trải qua vấn đề tương tự mà đưa tôi đến trang này.

@MartinSmith đã làm điều gì đó khi anh ấy đề nghị cập nhật số liệu thống kê và giải thích kế hoạch của bạn. Tôi muốn nói thêm rằng bạn cũng nên cố gắng đảm bảo bạn xem qua các công việc / truy vấn có thể tạo khóa và do đó làm chậm thời gian phản hồi.

Trong trường hợp của tôi, thủ phạm là số liệu thống kê bảng thu thập công việc. Vì một số lý do, nó không hoàn thành trong cửa sổ nên có và tiếp tục chạy khi người dùng đã tiếp tục. Tôi tìm thấy quá trình, giết nó và các truy vấn bắt đầu trả lời lại.

Tôi mong điều này giúp được người nào khác


0

Bạn cũng cần kiểm tra xem có bất kỳ bản sao lưu máy chủ hoặc bất kỳ công việc lưu trữ \ lập chỉ mục nào đang chạy hay không khi bạn thấy vấn đề về hiệu năng trong T-SQL \ Thủ tục.

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.