Bây giờ COALESCE có thể sargable?


9

Một trong những nhà phát triển của tôi đang tranh luận rằng COALESCE(column, default value) = default valuebây giờ có thể nói được. Có đúng không?

Tôi đã chạy thử nghiệm sau đây, và nghĩ rằng nó ngụ ý rằng COALESCEnó không thể nói được.

USE tempdb;

SELECT @@VERSION;
-- Microsoft SQL Server 2016 (RTM-CU3-GDR) (KB3194717) - 13.0.2186.6 (X64)   Oct 31 2016 18:27:32   Copyright (c) Microsoft Corporation  Developer Edition (64-bit) on Windows 10 Pro 6.3 <X64> (Build 14393: ) (Hypervisor) 

CREATE TABLE Test 
(
    ID int primary key clustered, 
    Mod6 int null, 
    INDEX IX_Mod6 NONCLUSTERED (Mod6)
);

INSERT INTO Test (ID, Mod6)
SELECT object_id as ID, case when name like '%k%' then null else object_id % 6 end as Mod6
FROM sys.objects;

SELECT Mod6
FROM Test WITH (INDEX = IX_Mod6, FORCESEEK)
where Mod6 is null or Mod6 = 0;
-- Plan shows expected seek

SELECT Mod6
FROM Test WITH (INDEX = IX_Mod6, FORCESEEK)
WHERE COALESCE(Mod6, 0) = 0;
-- Error:
-- Msg 8622, Level 16, State 1, Line 20
-- Query processor could not produce a query plan because of the hints 
-- defined in this query. Resubmit the query without specifying any hints 
-- and without using SET FORCEPLAN.

5
Nhà phát triển của bạn đã tranh luận với bất kỳ bằng chứng nào?
Aaron Bertrand

Tôi đọc bài đăng này: josef-richberg.squarespace.com/journal/2010/1/28/ nam Tôi không nghĩ rằng một câu trả lời cụ thể có thể được rút ra để trả lời bài đăng này. (Nhưng có lẽ ai đó biết rõ hơn.)
RLF

@RLF - bài viết đó không nói bất cứ điều gì có thể chỉ ra rằng nó có thể nói được. Đây không phải là một minh chứng cho việc nó có thể nói được. twitpic.com/107ms0 . Tính không khả thi là nó ngăn tìm kiếm trên các cột được sử dụng trong CASEbiểu thức - không phải là kết quả của biểu thức sau đó không thể được sử dụng để tìm kiếm một thứ khác.
Martin Smith

@AaronBertrand, "Kế hoạch thực hiện trông giống nhau cho dù tôi viết nó như thế nào" - Ông bỏ qua thực tế là cả hai đều không thực hiện tìm kiếm dựa trên COALESCEcột d.
Mitch

1
Ồ tôi không có lỗi với bạn khi đặt câu hỏi, đặc biệt là khi bạn đã cố gắng từ chối nó trước. Tôi chỉ gợi ý rằng có lẽ nhà phát triển của bạn nên học cách làm tương tự.
Aaron Bertrand

Câu trả lời:


15

Không COALESCElà không thể nói được.

Thử nghiệm của riêng bạn chứng minh điều này tốt.

Một ngoại lệ sẽ là nếu bạn tạo một cột được tính toán với COALESCEbiểu thức và lập chỉ mục đó.

CREATE TABLE Test 
(
    ID int primary key clustered, 
    Mod6 int null, 
    Foo AS COALESCE(Mod6, 0),
    INDEX IX_Mod6 NONCLUSTERED (Mod6),
    INDEX IX2_Mod6 NONCLUSTERED (Foo),
);

Bạn có thể kết thúc với một tìm kiếm về điều đó

SELECT Mod6
FROM Test WITH (INDEX = IX2_Mod6, FORCESEEK)
WHERE COALESCE(Mod6, 0) = 0;

ISNULL đáng chú ý hơn nhiều nếu nó hoàn toàn dư thừa, nó có thể được tối ưu hóa và không ngăn cản việc tìm kiếm.

tức là nếu cột Mod6được định nghĩa như NOT NULLsau thì có thể tạo ra một tìm kiếm.

SELECT Mod6
FROM Test 
WHERE ISNULL(Mod6, 0) = 0;

Nhưng điều này tất nhiên không cung cấp bất kỳ lợi ích nào so với chỉ làm

WHERE Mod6 = 0
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.