Truy vấn là
SELECT SUM(Amount) AS SummaryTotal
FROM PDetail WITH(NOLOCK)
WHERE ClientID = @merchid
AND PostedDate BETWEEN @datebegin AND @dateend
Bảng chứa 103.129.000 hàng.
Gói nhanh được tra cứu bởi ClientId với một vị từ còn lại vào ngày nhưng cần thực hiện 96 lần tra cứu để truy xuất Amount
. Các <ParameterList>
phần trong kế hoạch thực hiện như sau.
<ParameterList>
<ColumnReference Column="@dateend"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@datebegin"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@merchid"
ParameterRuntimeValue="(78155)" />
</ParameterList>
Kế hoạch chậm tìm kiếm theo ngày và có tra cứu để đánh giá vị từ còn lại trên ClientId và để lấy số tiền (Ước tính 1 so với thực tế 7,388,383). Các <ParameterList>
phần là
<ParameterList>
<ColumnReference Column="@EndDate"
ParameterCompiledValue="'2013-02-01 23:59:00.000'"
ParameterRuntimeValue="'2013-02-01 23:59:00.000'" />
<ColumnReference Column="@BeginDate"
ParameterCompiledValue="'2013-01-01 00:00:00.000'"
ParameterRuntimeValue="'2013-01-01 00:00:00.000'" />
<ColumnReference Column="@ClientID"
ParameterCompiledValue="(78155)"
ParameterRuntimeValue="(78155)" />
</ParameterList>
Trong trường hợp thứ hai ParameterCompiledValue
này không trống. SQL Server đã đánh hơi thành công các giá trị được sử dụng trong truy vấn.
Cuốn sách "Xử lý sự cố thực tế SQL Server 2005" có nội dung này để nói về việc sử dụng các biến cục bộ
Sử dụng các biến cục bộ để đánh bại tham số đánh hơi là một mẹo khá phổ biến, nhưng các gợi ý OPTION (RECOMPILE)
và OPTION (OPTIMIZE FOR)
... nói chung là các giải pháp thanh lịch hơn và ít rủi ro hơn
Ghi chú
Trong SQL Server 2005, biên dịch mức câu lệnh cho phép biên dịch một câu lệnh riêng lẻ trong một thủ tục được lưu trữ được hoãn lại cho đến trước khi thực hiện truy vấn đầu tiên. Đến lúc đó giá trị của biến cục bộ sẽ được biết đến. Về mặt lý thuyết, SQL Server có thể lợi dụng điều này để đánh hơi các giá trị biến cục bộ giống như cách nó đánh hơi các tham số. Tuy nhiên, vì thông thường sử dụng các biến cục bộ để đánh bại tham số đánh hơi trong SQL Server 7.0 và SQL Server 2000+, việc đánh hơi các biến cục bộ không được kích hoạt trong SQL Server 2005. Nó có thể được kích hoạt trong bản phát hành SQL Server trong tương lai. lý do để sử dụng một trong các tùy chọn khác được nêu trong chương này nếu bạn có lựa chọn.
Từ một thử nghiệm nhanh, kết thúc này, hành vi được mô tả ở trên vẫn giống nhau trong năm 2008 và 2012 và các biến không được đánh hơi để biên dịch bị trì hoãn mà chỉ khi sử dụng một OPTION RECOMPILE
gợi ý rõ ràng .
DECLARE @N INT = 0
CREATE TABLE #T ( I INT );
/*Reference to #T means this statement is subject to deferred compile*/
SELECT *
FROM master..spt_values
WHERE number = @N
AND EXISTS(SELECT COUNT(*) FROM #T)
SELECT *
FROM master..spt_values
WHERE number = @N
OPTION (RECOMPILE)
DROP TABLE #T
Mặc dù biên dịch bị hoãn, biến không được đánh hơi và số lượng hàng ước tính là không chính xác
Vì vậy, tôi giả định rằng kế hoạch chậm liên quan đến một phiên bản tham số của truy vấn.
Giá trị ParameterCompiledValue
này bằng ParameterRuntimeValue
với tất cả các tham số, vì vậy đây không phải là đánh hơi tham số điển hình (trong đó kế hoạch được biên dịch cho một bộ giá trị sau đó chạy cho một bộ giá trị khác).
Vấn đề là kế hoạch được biên dịch cho các giá trị tham số chính xác là không phù hợp.
Bạn có thể gặp phải vấn đề với ngày tăng dần được mô tả ở đây và đây . Đối với một bảng có 100 triệu hàng, bạn cần chèn (hoặc sửa đổi) 20 triệu trước khi SQL Server sẽ tự động cập nhật số liệu thống kê cho bạn. Có vẻ như lần trước chúng được cập nhật các hàng không khớp với phạm vi ngày trong truy vấn nhưng hiện có 7 triệu.
Bạn có thể lên lịch cập nhật thống kê thường xuyên hơn, xem xét các cờ theo dõi 2389 - 90
hoặc sử dụng OPTIMIZE FOR UKNOWN
để nó chỉ dựa vào dự đoán thay vì có thể sử dụng số liệu thống kê hiện đang gây hiểu lầm trên datetime
cột.
Điều này có thể không cần thiết trong phiên bản tiếp theo của SQL Server (sau năm 2012). Một mục Kết nối có liên quan chứa phản hồi hấp dẫn
Được đăng bởi Microsoft vào ngày 28/8/2012 lúc 1:35 PM
Chúng tôi đã thực hiện nâng cao ước tính cardinality cho phiên bản chính tiếp theo mà về cơ bản là khắc phục điều này. Hãy theo dõi để biết chi tiết khi xem trước của chúng tôi đi ra. Eric
Cải tiến năm 2014 này được xem xét bởi Benjamin Nevarez cho đến cuối bài viết:
Cái nhìn đầu tiên về Công cụ ước tính số lượng máy chủ SQL mới .
Có vẻ như công cụ ước tính cardinality mới sẽ quay trở lại và sử dụng mật độ trung bình trong trường hợp này thay vì đưa ra ước tính 1 hàng.
Một số chi tiết bổ sung về công cụ ước tính cardinality 2014 và vấn đề chính tăng dần ở đây:
Chức năng mới trong SQL Server 2014 - Phần 2 - Ước tính Cardinality mới