Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

chọn sự suy giảm hiệu suất trạng thái khi sử dụng DISTINCT với các tham số

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách tìm vị trí của tệp dữ liệu và tệp nhật ký trong SQL Server

  2. Khôi phục SQL Server 2017

  3. Nhật ký giao dịch SQL Server, Phần 2:Kiến trúc nhật ký

  4. Ứng dụng khách có địa chỉ IP không được phép truy cập vào cơ sở dữ liệu Azure SQL của máy chủ

  5. Bảng có nhiều cột