Có, nó sẽ.
Có hai điểm khác biệt chính giữa OPTION(OPTIMIZE FOR UNKNOWN)
và OPTION(RECOMPILE)
như có thể thấy từ trích dẫn này từ MSDN
:
Vì vậy, hai điểm khác biệt chính là:
- Lưu vào bộ nhớ đệm (hoặc không) của kế hoạch truy vấn.
Thông thường, kế hoạch truy vấn được tạo sẽ được lưu vào bộ nhớ đệm và sử dụng lại. OPTIMIZE FOR UNKNOWN
không ảnh hưởng đến tính năng này của động cơ. RECOMPILE
ngăn chặn tính năng này và yêu cầu công cụ loại bỏ kế hoạch và không đưa nó vào bộ nhớ cache.
- Sử dụng (hoặc không) các giá trị thông số thực tế trong quá trình tạo kế hoạch.
Thông thường trình tối ưu hóa "đánh hơi" các giá trị tham số và sử dụng các giá trị này khi tạo kế hoạch. OPTIMIZE FOR UNKNOWN
ngăn chặn tính năng này và yêu cầu động cơ xử lý tất cả các tham số như thể giá trị của chúng là không xác định. Trình tối ưu hóa có các quy tắc tích hợp và phương pháp phỏng đoán cách sử dụng thống kê có sẵn cho các tiêu chí lọc khác nhau. Xem Tối ưu hóa cho… Mediocre?
để biết thêm chi tiết. Thông thường, tính năng dò tìm tham số được sử dụng trong lần chạy đầu tiên của thủ tục truy vấn / được lưu trữ và sử dụng giá trị của các tham số trong lần chạy đầu tiên. Kế hoạch đã tạo được lưu vào bộ nhớ đệm và sau này có thể được sử dụng lại.
Một điều không rõ ràng cần nhớ ở đây là trong cả hai trường hợp (bình thường không có bất kỳ gợi ý truy vấn nào và với OPTIMIZE FOR UNKNOWN
gợi ý) kế hoạch đã tạo phải hợp lệ và tạo ra kết quả chính xác cho bất kỳ giá trị tham số có thể. Nó được điều chỉnh cho phù hợp với các giá trị đánh hơi được sử dụng trong lần chạy đầu tiên trong trường hợp bình thường / không có gợi ý; nó không được điều chỉnh cho phù hợp với bất kỳ giá trị cụ thể nào trong OPTIMIZE FOR UNKNOWN
nhưng nó vẫn hợp lệ nếu sau này tham số thay đổi theo bất kỳ cách nào.
Điều này rất quan trọng và nó ngăn trình tối ưu hóa thực hiện một số chuyển đổi và đơn giản hóa kế hoạch.
OPTION(RECOMPILE)
cho phép trình tối ưu hóa nội tuyến các giá trị thực tế của các tham số trong mỗi lần chạy và trình tối ưu hóa sử dụng các giá trị thực tế của các tham số để tạo ra một kế hoạch tốt hơn. Bạn không cần phải lo lắng rằng kế hoạch đã tạo có thể không hoạt động với một số giá trị khác của tham số, bởi vì kế hoạch sẽ không được lưu vào bộ nhớ cache và sử dụng lại.
Hiệu ứng này hầu như có thể nhìn thấy đối với Điều kiện tìm kiếm động truy vấn. Ví dụ:
SELECT ...
FROM T
WHERE
(@ParamSomeID = 0)
OR
(
@ParamSomeID = -1
AND
T.SomeID NOT IN
(
SELECT OtherTable.SomeID
FROM OtherTable
)
)
OR
(
T.SomeID IN
(
SELECT OtherTable.SomeID
FROM OtherTable
WHERE OtherTable.SomeID = @ParamSomeID
)
)
OPTION(RECOMPILE)
Nếu @ParamSomeID
là 0
trình tối ưu hóa sẽ coi truy vấn như thể nó không có bất kỳ WHERE
nào mệnh đề nào cả. Kế hoạch sẽ không đề cập đến OtherTable
ở tất cả.
Nếu @ParamSomeID
là -1
, kế hoạch sẽ tham gia T
thành OtherTable
bằng cách sử dụng Left Anti Semi Join và sẽ quét toàn bộ OtherTable
.
Nếu @ParamSomeID
tức là, 5, kế hoạch sẽ thực hiện tìm kiếm chỉ mục trong chỉ mục duy nhất trên OtherTable
và chỉ đọc một hàng từ OtherTable
.
Không có OPTION(RECOMPILE)
kiểu đơn giản hóa và chuyển đổi sẽ không xảy ra.
Một lý do khác để sử dụng OPTION(RECOMPILE)
là khi phân phối dữ liệu của bạn rất lệch. Ví dụ:bạn có một bảng với 1 triệu hàng. Một cột có giá trị 0 trong 990 nghìn hàng và giá trị từ 1 đến 10 trong 1 nghìn hàng. Các truy vấn lọc trên cột này phải có các kế hoạch khác nhau tùy thuộc vào giá trị thực của bộ lọc.
Trong cả hai ví dụ ở trên, OPTIMIZE FOR UNKNOWN
sẽ tạo ra một kế hoạch tầm thường.