COALESCEは今でも検索可能ですか?


9

私の開発者の1人は、これCOALESCE(column, default value) = default valueが現在は反論の余地があると主張しています。そうですか?

私は次のテストを実行しましたが、それがCOALESCE反論できないことを意味すると思います。

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
あなたの開発者は、何らかの証拠を主張しましたか?
アーロンバートランド

私はこの投稿を読みました:josef-richberg.squarespace.com/journal/2010/1/28/…この投稿に 回答するための具体的な回答が得られるとは思いません。(しかし、おそらく他の誰かがよりよく知っています。)
RLF 2017年

@RLF-その記事は、それが捜査対象であることを示すようなことは何も述べていません。これはそれが反論されていることの実証ではありません。twitpic.com/107ms0。非検索可能性とは、CASE式で使用されている列のシークを防止することであり、式の結果を他の何かにシークするために使用できないことではありません。
マーティン・スミス

@AaronBertrand、「実行プランはどのように記述しても同じに見えました」-彼はどちらもCOALESCEd列に基づいてシークを実行していないという事実を無視しました。
ミッチ

1
特にあなたが最初にそれを反証しようとしたので、私はあなたが質問をすることについてあなたを責めません。たぶんあなたの開発者も同じことを学ぶべきだと提案しました。
アーロンバートランド

回答:


15

いいえCOALESCE、検索条件はありません。

あなた自身のテストはこれをよく示しています。

例外は、COALESCE式を使用して計算列を作成し、それにインデックスを付けた場合です。

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

あなたはそれを探すことになるかもしれません

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

ISNULL 完全に冗長である場合、最適化してシークを妨げることができないという点で、わずかに検索可能です。

つまり、列Mod6NOT NULL次のように定義されている場合、次のようにシークを生成できます。

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

しかし、もちろんこれは単に実行することよりも利点を提供しません

WHERE Mod6 = 0
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.