Hành vi bạn đang mô tả thường là do kế hoạch truy vấn được lưu trong bộ nhớ cache không chính xác và / hoặc thống kê lỗi thời.
Nó thường xảy ra khi bạn có một số lượng lớn các tham số trong mệnh đề WHERE, đặc biệt là một danh sách dài các tham số có dạng:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Giả sử, kế hoạch truy vấn được lưu trong bộ nhớ cache sẽ hết hạn và proc được gọi với một bộ tham số không đại diện. Kế hoạch sau đó được lưu vào bộ nhớ cache cho hồ sơ dữ liệu này. NHƯNG, nếu proc thường phổ biến hơn với một bộ thông số rất khác, kế hoạch có thể không phù hợp. Điều này thường được gọi là 'đánh giá tham số'.
Có nhiều cách để giảm thiểu và loại bỏ vấn đề này nhưng chúng có thể liên quan đến sự đánh đổi và phụ thuộc vào phiên bản SQL Server của bạn. Xem OPTIMIZE FOR
và OPTIMIZE FOR UNKNOWN
. IF (và đó là một điều lớn nếu) proc không thường xuyên được gọi nhưng phải chạy càng nhanh càng tốt, bạn có thể đánh dấu nó là OPTION(RECOMPILE)
, để buộc biên dịch lại mỗi khi nó được gọi, NHƯNG không làm điều này đối với các procs thường được gọi là HOẶC mà không cần điều tra.
[LƯU Ý:hãy biết Gói dịch vụ và Cập nhật tích lũy (CU) hộp SQL Server 2008 của bạn có, vì logic kiểm tra tham số và biên dịch hoạt động khác nhau trong một số phiên bản]
Chạy truy vấn này (từ Glenn Berry) để xác định trạng thái thống kê:
-- When were Statistics last updated on all indexes?
SELECT o.name, i.name AS [Index Name],
STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date],
s.auto_created, s.no_recompute, s.user_created, st.row_count
FROM sys.objects AS o WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON o.[object_id] = i.[object_id]
INNER JOIN sys.stats AS s WITH (NOLOCK)
ON i.[object_id] = s.[object_id]
AND i.index_id = s.stats_id
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)
ON o.[object_id] = st.[object_id]
AND i.[index_id] = st.[index_id]
WHERE o.[type] = 'U'
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE);