2009-09-18 32 views
6

Tôi có điều khoản này trên tham gia trong một thủ tục lưu trữ Tôi được thừa kế:T-SQL ISNULL() Tối ưu hóa

WHERE a.is_active = 1 
AND b.due_date <= ISNULL(@due_date_limit, b.due_date) 

Làm thế nào tôi lại viết những dòng này để loại bỏ các ISNULL vì nó gây ra vấn đề hiệu suất nghiêm trọng?

+0

SQL Server phiên bản? – AnthonyWJones

Trả lời

7

trong trường hợp này, tôi sẽ có một câu lệnh if, kiểm tra @due_date_limit

IF (@due_date_limit IS NULL) 
BEGIN 
    ... 
    WHERE a.is_active = 1 --not required to compare b.due_date <= b.due_date 
END 
ELSE 
BEGIN 
    ... 
    WHERE a.is_active = 1 
    AND  b.due_date <= @due_date_limit 
END 
2
AND @due_date_limit IS NULL OR b.due_date <= @due_date_limit 

nhưng tôi không chắc nó sẽ nhanh hơn nhiều.

+0

Nếu có chỉ mục. – recursive

+0

Một chỉ mục không phải là mối quan tâm - ngay cả khi một chỉ mục tồn tại, chỉ mục sẽ chỉ được sử dụng trong nửa thứ hai. Nó tốt hơn nhiều so với đề xuất ISNULL/COALESCE. –

1

@due_date_limit là một biến thủ tục lưu trữ để nó có thể là yếu tố ra từ truy vấn này tất cả cùng nhau:

if (@due_date_limit is NULL) 
    <run query that works when @due_date_limit is NULL> 
else 
    <run query that works when @due_date_limit is NOT NULL> 
1
COALESCE(@due_date_limit, b.due_date) 

có thể giúp

+0

Điều này sẽ xử lý mọi thứ một cách duyên dáng, nhưng đó là một sự lãng phí để thực hiện 1 = 1 tương đương. –

2

có chỉ mục vào ngày Due_Date không? Nếu không thêm một và sau đó kiểm tra hiệu suất. Nếu có được, sau đó thay đổi để hai báo cáo riêng biệt

If @due_date_limit is null 
    Select [stuff] 
    From Table 
    Else 
    Select [stuff] 
    From Table 
    Where b.due_date <= @due_date_limit 

Nhưng nhận ra rằng không lọc (khi @due_date_limit là null), hoặc lọc sử dụng một < = khả năng có thể trả về một số lượng đáng kể các hồ sơ đó sẽ loại bỏ bất kỳ cơ hội để sử dụng chỉ mục và sẽ yêu cầu quét toàn bộ bảng. Đây có thể là những gì bạn đang gặp phải.

3

Nguyên nhân phổ biến nhất cho hiệu suất kém với loại truy vấn này là do trình tối ưu hóa không thể chắc chắn giá trị thông thường của @due_date_limit sẽ dành cho hầu hết các truy vấn. Thường thì kế hoạch được tạo ra và tái sử dụng bởi các thực thi tiếp theo sẽ ưu tiên trường hợp giá trị là null.

Tính đến SQL 2005 bạn có thể hướng dẫn optimizer sử dụng "tối ưu hóa cho" tùy chọn: -

WHERE a.is_active = 1 
AND b.due_date <= ISNULL(@due_date_limit, b.due_date) 
OPTION (OPTIMIZE FOR (@due_date_limit = '09/01/2009')) 
+0

Nếu tham số là null, tại sao bạn vẫn muốn so sánh các giá trị? Bạn không, do đó, không sử dụng ISNULL/COALESCE cho các tham số tùy chọn. –

0

Kể từ @due_date_limit là một biến thủ tục lưu trữ, bạn chỉ có thể kiểm tra xem nó cho NULL trước khi truy vấn và đặt nó với giá trị mặc định nếu cần, do đó loại bỏ kiểm tra ISNULL trong mệnh đề WHERE.

IF (@due_date_limit IS NULL) 
BEGIN 
    SET @due_date_limit = '09/01/2009'; 
END 

và sau đó khoản WHERE của bạn chỉ đơn giản là sẽ trông như thế này:

WHERE a.is_active = 1 
AND b.due_date <= @due_date_limit 
+0

Câu trả lời của người đọc là giải pháp tốt hơn nếu bạn cần nó giống như bản ghi cột để đáp ứng điều kiện vận hành '<=', nếu không đặt trước truy vấn như thế này vì nó sẽ nhanh hơn và không có kiểm tra. – johntrepreneur