Vấn đề không phải là DISTINCT đang gây ra sự suy giảm hiệu suất với các tham số, mà là phần còn lại của truy vấn không được tối ưu hóa trong truy vấn được tham số hóa bởi vì trình tối ưu hóa sẽ không chỉ tối ưu hóa tất cả các liên kết bằng cách sử dụng [email protected] _ADMINISTRATOR sẽ thích nó chỉ với 1 =1. Nó sẽ không tối ưu hóa các liên kết mà không có khác biệt vì nó cần trả về các bản sao dựa trên kết quả của các phép nối.
Tại sao? Bởi vì kế hoạch thực thi loại bỏ tất cả các phép nối sẽ không hợp lệ đối với bất kỳ giá trị nào khác ngoài @IS_ADMINISTRATOR =1. Nó sẽ không bao giờ tạo ra kế hoạch đó bất kể bạn có đang lưu kế hoạch trong bộ nhớ đệm hay không.
Điều này thực hiện tốt như truy vấn không được tham số hóa trên máy chủ 2008 của tôi:
-- PARAMETRIZED QUERY
declare @IS_ADMINISTRATOR int
declare @User_ID int
set @IS_ADMINISTRATOR = 1 -- 1 for administrator 0 for normal
set @User_ID = 50
IF 1 = @IS_ADMINISTRATOR
BEGIN
SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!!
DOC.DOCUMENT_ID
FROM
DOCUMENTS DOC LEFT OUTER JOIN
FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN
ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID)
WHERE
1 = 1
END
ELSE
BEGIN
SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!!
DOC.DOCUMENT_ID
FROM
DOCUMENTS DOC LEFT OUTER JOIN
FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN
ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID)
WHERE
ROL.USER_ID = @USER_ID
END
Điều rõ ràng từ kế hoạch truy vấn mà tôi thấy khi chạy ví dụ của bạn là @IS_ADMINISTRATOR = 1
không được tối ưu hóa giống như 1=1
. Trong ví dụ không tham số của bạn, các JOINS được tối ưu hóa hoàn toàn và nó chỉ trả về mọi id trong bảng DOCUMENTS (rất đơn giản).
Ngoài ra còn thiếu các tối ưu hóa khác nhau khi @IS_ADMINISTRATOR <> 1
. Ví dụ:LEFT OUTER JOIN
S được tự động thay đổi thành INNER JOIN
s không OR
đó mệnh đề, nhưng chúng được để nguyên như với điều đó hoặc điều khoản.
Xem thêm câu trả lời này: SQL LIKE% FOR INTEGERS cho một thay thế SQL động.
Tất nhiên, điều này không thực sự giải thích sự khác biệt về hiệu suất trong câu hỏi ban đầu của bạn, vì bạn không có OR trong đó. Tôi cho rằng đó là một sự giám sát.