Ist COALESCE jetzt sargable?

9

Einer meiner Entwickler argumentiert, dass COALESCE(column, default value) = default valuedas jetzt sargable ist. Ist das richtig?

Ich habe den folgenden Test durchgeführt und denke, dies impliziert, dass dies COALESCEnicht sargable ist.

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.
Mitch
quelle
5
Hat Ihr Entwickler mit irgendwelchen Beweisen gestritten?
Aaron Bertrand
Ich habe diesen Beitrag gelesen: josef-richberg.squarespace.com/journal/2010/1/28/… Ich glaube nicht, dass eine konkrete Antwort abgeleitet werden kann, um diesen Beitrag zu beantworten. (Aber vielleicht weiß es jemand anderes besser.)
RLF
@RLF - dieser Artikel sagt nichts, was darauf hindeuten würde, dass es sargable ist. Dies ist keine Demonstration dafür, dass es sargable ist. twitpic.com/107ms0 . Die Nicht-Sargabilität besteht darin, dass eine Suche in den im CASEAusdruck verwendeten Spalten verhindert wird - nicht, dass das Ergebnis des Ausdrucks dann nicht dazu verwendet werden kann, nach etwas anderem zu suchen.
Martin Smith
@AaronBertrand, "Der Ausführungsplan sah gleich aus, egal wie ich ihn schreibe" - Er ignorierte die Tatsache, dass keiner der beiden eine Suche basierend auf der COALESCESpalte d durchführte.
Mitch
1
Oh, ich beschuldige Sie nicht, die Frage gestellt zu haben, zumal Sie zuerst versucht haben, sie zu widerlegen. Ich habe nur vorgeschlagen, dass Ihr Entwickler vielleicht lernen sollte, dasselbe zu tun.
Aaron Bertrand

Antworten:

15

Nein COALESCEist nicht sargable.

Ihr eigener Test zeigt dies gut.

Eine Ausnahme wäre, wenn Sie eine berechnete Spalte mit dem COALESCEAusdruck erstellt und diesen indiziert hätten.

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),
);

Sie könnten am Ende eine Suche danach haben

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

ISNULL ist insofern etwas sarkastischer, als es, wenn es völlig redundant ist, optimiert werden kann und eine Suche nicht verhindert.

Wenn die Spalte Mod6als definiert ist, NOT NULLkann Folgendes eine Suche erzeugen.

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

Aber das bringt natürlich keinen Vorteil gegenüber dem bloßen Tun

WHERE Mod6 = 0
Martin Smith
quelle