아래 쿼리에서 두 실행 계획은 고유 인덱스에 대해 1,000 회의 검색을 수행하는 것으로 추정됩니다.
탐색은 동일한 소스 테이블에서 정렬 된 스캔에 의해 수행되므로 동일한 순서로 동일한 값을 찾는 것으로 보입니다.
두 개의 중첩 루프는 <NestedLoops Optimized="false" WithOrderedPrefetch="true">
왜이 작업이 첫 번째 계획에서는 0.172434이고 두 번째 계획에서는 3.01702의 비용이 드는지 아는 사람이 있습니까?
(질문의 이유는 첫 번째 쿼리가 계획 비용이 훨씬 낮기 때문에 최적화로 제안 되었기 때문입니다. 실제로 더 많은 작업을하는 것처럼 보이지만 불일치를 설명하려고합니다. .)
설정
CREATE TABLE dbo.Target(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);
CREATE TABLE dbo.Staging(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);
INSERT INTO dbo.Target
SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1,
master..spt_values v2;
INSERT INTO dbo.Staging
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1;
쿼리 1 "계획 붙여 넣기"링크
WITH T
AS (SELECT *
FROM Target AS T
WHERE T.KeyCol IN (SELECT S.KeyCol
FROM Staging AS S))
MERGE T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
INSERT ( KeyCol, OtherCol )
VALUES(S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
UPDATE SET T.OtherCol = S.OtherCol;
쿼리 2 "계획 붙여 넣기"링크
MERGE Target T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
INSERT ( KeyCol, OtherCol )
VALUES( S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
UPDATE SET T.OtherCol = S.OtherCol;
쿼리 1
쿼리 2
위의 내용은 SQL Server 2014 (SP2) (KB3171021)-12.0.5000.0 (X64)에서 테스트되었습니다.
@Joe Obbish 는 더 단순한 재현이 될 것이라고 의견에서 지적합니다.
SELECT *
FROM staging AS S
LEFT OUTER JOIN Target AS T
ON T.KeyCol = S.KeyCol;
vs
SELECT *
FROM staging AS S
LEFT OUTER JOIN (SELECT * FROM Target) AS T
ON T.KeyCol = S.KeyCol;
의 모두 1,000 행 스테이징 테이블 위에서 정지 파생 테이블없이 중첩 루프와 동일한 평면 형상 및 평면이 나타나는 저렴하지만, 비용의 차이 위와 10,000 행 스테이징 테이블과 동일한 목표 테이블의 계획을 변경하지 이러한 비용 불일치가 계획을 비교하는 것을 어렵게하는 것 외에 다른 영향을 미칠 수 있음을 보여주는 형태 (전체 스캔 및 병합 조인이 비용이 많이 드는 검색보다 상대적으로 매력적으로 보입니다).