COALESCE est-il désormais sargable?

9

Un de mes développeurs fait valoir que COALESCE(column, default value) = default valuec'est désormais discutable. Est-ce correct?

J'ai exécuté le test suivant, et je pense que cela implique que ce COALESCEn'est pas discutable.

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
la source
5
Votre développeur a-t-il contesté la moindre preuve?
Aaron Bertrand
J'ai lu ce post: josef-richberg.squarespace.com/journal/2010/1/28/… Je ne pense pas qu'une réponse concrète puisse être dérivée pour répondre à ce post. (Mais peut-être que quelqu'un d'autre sait mieux.)
RLF
@RLF - cet article ne dit rien qui indiquerait qu'il est discutable. Ce n'est pas une démonstration qu'il est discutable. twitpic.com/107ms0 . La non-sargabilité est qu'elle empêche une recherche sur les colonnes utilisées dans l' CASEexpression - pas que le résultat de l'expression ne puisse pas ensuite être utilisé pour rechercher autre chose.
Martin Smith
@AaronBertrand, "Le plan d'exécution a la même apparence, peu importe comment je l'écris" - Il a ignoré le fait qu'aucun des deux n'effectuait une recherche basée sur la COALESCEcolonne d.
Mitch
1
Oh, je ne vous blâme pas d'avoir posé la question, surtout depuis que vous avez essayé de la réfuter en premier. Je suggérais simplement que votre développeur devrait peut-être apprendre à faire de même.
Aaron Bertrand

Réponses:

15

Non COALESCEn'est pas discutable.

Votre propre test le démontre bien.

Une exception serait si vous créez une colonne calculée avec l' COALESCEexpression et l'indexez.

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

Vous pourriez vous retrouver avec une recherche sur ce

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

ISNULL est légèrement plus discutable dans la mesure où s'il est totalement redondant, il peut être optimisé et ne pas empêcher une recherche.

c'est-à-dire que si la colonne Mod6est définie comme NOT NULLalors, ce qui suit peut produire une recherche.

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

Mais cela, bien sûr, n'apporte aucun avantage par rapport à simplement faire

WHERE Mod6 = 0
Martin Smith
la source