2009-09-03 72 views
6

Tôi cố gắng để tối ưu hóa một truy vấn mà làm điều gì đó như thế này:Biểu thức SQLServer CASE - đánh giá ngắn mạch?

SELECT 
    ... 
    CASE WHEN (condition) THEN (expensive function call #1) 
    ELSE (expensive function call #2) 
    END 
... 

Kế hoạch truy vấn cho thấy đối với ngay cả trong trường hợp 100% các hàng thỏa mãn các quy định tại khoản KHI, một phần đáng kể thời gian là chi tiêu trong gọi đến kết quả trong nhánh ELSE. Cách duy nhất tôi có thể hiểu được điều này là giả sử rằng SQLServer đang đánh giá cả hai kết quả, sau đó chỉ chọn một dựa trên đánh giá điều kiện WHEN, nhưng tôi không thể tìm thấy bất kỳ tham chiếu dứt khoát nào cho dù có hay không kết quả của một câu lệnh CASE được đánh giá trước các điều kiện. Bất cứ ai có thể vui lòng làm rõ hoặc chỉ cho tôi một tham chiếu?

+0

Tôi không thể xác nhận điều này, ngay cả khi tôi thử một hàm đắt tiền truy vấn một bảng lớn. Nếu tôi đặt phần đầu tiên của CASE thành đúng 100% nếu thời gian, truy vấn của tôi mất 5 giây. Nếu không, khoảng 10 phút. Phiên bản SQL Server nào? – MartW

Trả lời

1

Đó có phải là kế hoạch thực tế hoặc ước tính không? Sql Server xây dựng kế hoạch dựa trên những gì nó dự kiến ​​sẽ làm dựa trên số liệu thống kê thu thập được, và điều đó không phải lúc nào cũng phù hợp với những điều kiện cụ thể mà bạn gửi cho một ví dụ của một truy vấn chạy.

+0

Rất tiếc, tất nhiên là vậy. Khi truy vấn thực tế được thực thi, kế hoạch trông hoàn toàn khác. Xin lỗi vì đã không nghĩ về điều đó trước. –

9

SQL là ngôn ngữ khai báo. Bạn thể hiện trong một truy vấn kết quả mong muốn và máy chủ được tự do lựa chọn bất kỳ phương tiện nào để phân phối các kết quả đó. Như vậy thứ tự đánh giá các epxress SQL là không phải được xác định và ORAND ngắn mạch đánh giá không xảy ra.

Tuy nhiên đối với CASE tài liệu thực sự khẳng định rằng order of evaluation occurs in the order of declaration và đánh giá dừng lại sau khi điều kiện đầu tiên được đáp ứng:

  • Ước lượng input_expression, và sau đó theo thứ tự quy định, đánh giá input_expression = when_expression cho mỗi mệnh đề WHEN.

  • Trả lại số result_expression trong số đầu tiên đánh giá là TRUE.

Điều đó có nghĩa rằng nếu bạn nhìn thấy biểu hiện trong các chi nhánh FALSE đánh giá, tình trạng trường hợp của bạn là không chính xác và đôi khi đánh giá FALSE hoặc UNKNOWN. Đảm bảo rằng logic tri-giá trị của SQL được đưa vào tài khoản (ví dụ: bạn tài khoản cho NULL). Ngoài ra, hãy đảm bảo dữ liệu trong bảng là bảng bạn mong đợi (ví dụ: điều kiện thực sự là đánh giá thành FALSE 100% các trường hợp).

+0

Không hoàn toàn. Đã xảy ra lỗi trong Microsoft Connect, [Tổng hợp không tuân theo ngữ nghĩa của CASE] (https://connect.microsoft.com/SQLServer/feedback/details/691535/), đã chứng minh trường hợp thứ tự đánh giá của các biểu thức 'CASE' không được tôn trọng. Ngay cả [tài liệu MSDN] (http://msdn.microsoft.com/en-us/library/ms181765.aspx) đã được cập nhật: "Trong một số trường hợp, một biểu thức được đánh giá trước khi một câu lệnh CASE nhận được kết quả của biểu thức làm đầu vào của nó. " – Douglas

Các vấn đề liên quan