В нижеприведенных запросах оба плана выполнения оцениваются в 1000 запросов на уникальный индекс.
Поиски управляются упорядоченным сканированием одной и той же исходной таблицы, поэтому, по-видимому, в конечном итоге следует искать одинаковые значения в том же порядке.
Обе вложенные циклы имеют <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;
против
SELECT *
FROM staging AS S
LEFT OUTER JOIN (SELECT * FROM Target) AS T
ON T.KeyCol = S.KeyCol;
Для промежуточной таблицы из 1000 строк оба из перечисленных выше по-прежнему имеют одну и ту же форму плана с вложенными циклами, а план без производной таблицы, которая выглядит дешевле, но для промежуточной таблицы из 10 000 строк и той же целевой таблицы, что и выше, разница в стоимости действительно меняет план форма (с полным сканированием и объединением слиянием, кажущееся относительно более привлекательным, чем поиск с дорогой стоимостью), показывающий, что это несоответствие затрат может иметь иные последствия, чем просто усложнение сравнения планов.