¿COALESCE es sargable ahora?

9

Uno de mis desarrolladores está argumentando que COALESCE(column, default value) = default valueahora es sargable. ¿Está bien?

COALESCEEjecuté la siguiente prueba, y creo que implica que no es sargable.

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
fuente
55
¿Tu desarrollador discutió con alguna evidencia?
Aaron Bertrand
Leí esta publicación: josef-richberg.squarespace.com/journal/2010/1/28/… No creo que se pueda derivar una respuesta concreta para responder a esta publicación. (Pero tal vez alguien más lo sepa).
RLF
@RLF: ese artículo no dice nada que indique que es sargable. Esto no es una demostración de que sea sargable. twitpic.com/107ms0 . La no sargabilidad es que evita una búsqueda en las columnas utilizadas en la CASEexpresión, no es que el resultado de la expresión no pueda usarse para buscar en otra cosa.
Martin Smith
@AaronBertrand, "El plan de ejecución se veía igual sin importar cómo lo escribiera" - Ignoraba el hecho de que ninguno de los dos estaba realizando una búsqueda basada en la COALESCEcolumna d.
Mitch
1
Oh, no te culpo por hacer la pregunta, especialmente porque intentaste refutarla primero. Solo estaba sugiriendo que tal vez tu desarrollador debería aprender a hacer lo mismo.
Aaron Bertrand

Respuestas:

15

No COALESCEno es sargable.

Su propia prueba lo demuestra bien.

Una excepción sería si creara una columna calculada con la COALESCEexpresión y la indexara.

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

Podrías terminar con una búsqueda sobre eso

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

ISNULL es marginalmente más sargable en que si es totalmente redundante puede optimizarse y no evitar una búsqueda.

es decir, si la columna Mod6se define como NOT NULLentonces, lo siguiente puede producir una búsqueda.

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

Pero esto, por supuesto, no proporciona ningún beneficio sobre solo hacer

WHERE Mod6 = 0
Martin Smith
fuente