Thông số đánh hơi: Tại sao điều này trở thành một vấn đề?


7

Hôm nay, tôi gặp sự cố với thời gian thủ tục được lưu trữ (mất hơn 30 giây) khi nó được chạy từ trang web ASP.NET, nhưng được thực thi nhanh khi chạy từ SSMS (mất 5 giây).

Sau khi nghi ngờ tham số đánh hơi là thủ phạm, tôi che dấu các tham số đầu vào và truy vấn được thực hiện nhanh hơn.

Câu hỏi của tôi là: tại sao điều này xảy ra?

Hệ thống này đã được sản xuất hơn 5 năm và đây là lần đầu tiên chúng tôi thấy bất cứ điều gì như thế này trên các thủ tục được lưu trữ của chúng tôi. Đây có phải là "hao mòn cơ sở dữ liệu" không?

Chúng tôi đã giải quyết vấn đề, vì vậy nó không phải là vấn đề lớn, nhưng tôi chỉ tò mò về lý do tại sao điều này xảy ra.


Ngoài ra, hãy xem những điều này trên SO vui lòng: stackoverflow.com/
Kẻ

Tôi đã thấy điều này xảy ra khá nhiều. Ở phần cuối của hầu hết các tệp DROP/ CREATE PROC.sql của tôi , tôi thường bao gồm một tệp EXECcho sproc, với các tham số thực tế. Do đó, bất cứ khi nào sproc được tạo lại, nó sẽ được chạy một lần với các thông số tốt và (nên) có được một kế hoạch thực hiện tốt.
Jon của tất cả các giao dịch

Câu trả lời:


8

Về cơ bản những gì xảy ra là, khi SQL Server nhìn thấy một truy vấn mà nó cần biên dịch, nó sẽ sử dụng các tham số được gọi lần đầu tiên để tạo kế hoạch thực hiện. Điều này có thể hoặc không thể là một điều tốt, nhưng nó là những gì xảy ra.

Chẳng hạn, giả sử bạn có một bảng trái cây (100 hàng). Có 98 hàng là Apple và chỉ có 2 hàng chứa trái Orange. Nếu bạn truy vấn bảng đó cho Apple, thì kế hoạch rất có thể sẽ được biên dịch bằng Quét. Đây là một điều tốt, vì nó được tối ưu hóa cho truy vấn đó của Apple. Nhưng sau đó khi bạn muốn truy vấn Orange, Quét đó không hiệu quả. Nhưng đó là kế hoạch được lưu trữ đang được sử dụng.

Thực tế của vấn đề là nó xảy ra. Lúc nào chả vậy. Nó thường không phải là một vấn đề nổi bật, nhưng trong một số trường hợp, nó có thể là một vấn đề khá lớn. Một giải pháp cho vấn đề đánh hơi tham số xấu đang diễn ra là bạn có thể sử dụng OPTIMIZE FORgợi ý truy vấn để buộc SQL Server sử dụng các giá trị tham số nhất định khi tạo kế hoạch thực hiện khi biên dịch ban đầu.


3
+1 Hoặc sử dụng OPTIMIZE FOR UNKNOWNhoặc OPTION RECOMPILEnếu hình dạng kế hoạch thay đổi rộng rãi và không có một giá trị nào bạn có thể tối ưu hóa một cách có chủ ý.
Aaron Bertrand

@AaronBertrand Điểm tốt về những điều đó. Cá nhân tôi chưa bao giờ phải sử dụng OPTION RECOMPILE, vì tôi muốn giải quyết một kế hoạch được lưu trong bộ nhớ cache kém tối ưu hơn là biên dịch lại cho mỗi cuộc gọi.
Thomas Stringer

Trong một số trường hợp OPTION RECOMPILElà tốt hơn - tổng chi phí có thể nhỏ so với một kế hoạch thực sự tồi tệ.
Aaron Bertrand

@AaronBertrand Tôi tin điều đó. Bạn đã phải sử dụng một chút trong quá khứ của bạn ??
Thomas Stringer

Có, SQL động rất nhiều lông để tìm kiếm với nhiều tham số tùy chọn. OPTION RECOMPILEvà sau đó optimize for ad hoc workloadsthực sự có ích.
Aaron Bertrand

6

... nhưng được thực hiện nhanh chóng khi chạy từ SSMS (mất 5 giây)

Khá khó chịu, mặc định SSMS dành cho SET ARITHABORT ONphần lớn các thư viện máy khách (ADO .Net, ODBC, OLE DB) chỉ định SET ARITHABORT OFF. Có thể bạn đã có một kế hoạch "xấu đi" nhưng khi bạn cố gắng sao chép qua SSMS, sự khác biệt trong ARITHABORT dẫn đến một kế hoạch khác được sử dụng, đó là "tốt".

Chậm trong ứng dụng, nhanh trong SSMS? là một tài liệu tham khảo tuyệt vời cho việc này.

Tại sao điều này xảy ra?

Rất có thể một biên dịch lại đã được kích hoạt và thật không may, một bộ đầu vào không điển hình đã được sử dụng để biên dịch.

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.