COALESCE는 현재 Sargable입니까?


9

저의 개발자 중 한 명이 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
개발자가 어떤 증거를 가지고 논쟁 했습니까?
Aaron Bertrand

이 게시물을 읽었습니다 : josef-richberg.squarespace.com/journal/2010/1/28/… 이 게시물에 대한 답변을 얻을 수있는 구체적인 답변은 없습니다. (그러나 다른 사람이 더 잘 알고있을 수도 있습니다.)
RLF

@RLF-그 기사는 그것이 다루기 쉽다는 것을 나타내는 어떤 것도 말하지 않습니다. 이것은 사르 기 가능하다는 것을 보여주는 것이 아닙니다. twitpic.com/107ms0 . 비 Sargability는 CASE표현식의 결과가 다른 것을 탐색하는 데 사용될 수 없다는 것이 아니라 표현식에 사용 된 열에 대한 탐색을 방지 한다는 것입니다.
Martin Smith

@AaronBertrand, "실행 계획은 작성 방법에 관계없이 동일하게 보였습니다" COALESCE-d 열을 기반으로 한 탐색을 수행하지 않았다는 사실을 무시했습니다 .
Mitch

1
오, 나는 당신이 질문을 한 것에 대해 당신을 잘못 생각하지 않습니다. 개발자가 똑같이하는 법을 배워야한다고 제안했습니다.
Aaron Bertrand

답변:


15

No COALESCE는 sargable이 아닙니다.

당신의 테스트는 이것을 잘 보여줍니다.

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.