Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Инструкция MERGE. План  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1668
Добрый день. Есть примерная инструкция MERGE
            MERGE PricelistLine AS pl
            USING
            (
              SELECT
                sp.Id_Article,
                sp.Price,
                sp.AllowDiscount,
                sp.MeasureUnitCode,
                sp.MinimumQuantity,
                @Id_PricelistHeader AS Id_PricelistHeader
              FROM
                #SalesPrice AS sp
              WHERE
                COALESCE(sp.WarehouseCode, N'') = COALESCE(@WarehouseCode, N'') AND
                sp.CurrencyCode = @CurrencyCode AND
                sp.SalesCode = @SalesCode
            ) AS src
            ON pl.Id_PricelistHeader = src.Id_PricelistHeader
            WHEN NOT MATCHED BY TARGET THEN

В предварительном плане есть такой кусок (прикрепил изображение, думаю достаточно).
Почему он решил использовать FULL OUTER JOIN в MERGE JOIN и почему у него пустой WHERE (собственно поэтому наверное и FULL).
С какого такого он решил что WHERE условия нет для логического объединения поднаборов?

К сообщению приложен файл. Размер - 33Kb
7 авг 17, 12:29    [20704945]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1668
Ну собственно почему FULL OUTER JOIN я нашел
The WHEN NOT MATCHED BY TARGET clause and the WHEN NOT MATCHED BY SOURCE clause are specified. The WHEN MATCHED might or might not be specified.

А куда делись Conditions в нем?
7 авг 17, 12:34    [20704973]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
msLex
Member

Откуда:
Сообщений: 7730
X-Cite
Ну собственно почему FULL OUTER JOIN я нашел
The WHEN NOT MATCHED BY TARGET clause and the WHEN NOT MATCHED BY SOURCE clause are specified. The WHEN MATCHED might or might not be specified.

А куда делись Conditions в нем?



Потому что


@Id_PricelistHeader AS Id_PricelistHeader

pl.Id_PricelistHeader = src.Id_PricelistHeader


Ищите предикат в сканировании кластерного индекса PricelistLine
7 авг 17, 12:48    [20705058]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
msLex
Member

Откуда:
Сообщений: 7730
msLex
X-Cite
Ну собственно почему FULL OUTER JOIN я нашел
The WHEN NOT MATCHED BY TARGET clause and the WHEN NOT MATCHED BY SOURCE clause are specified. The WHEN MATCHED might or might not be specified.

А куда делись Conditions в нем?



Потому что


@Id_PricelistHeader AS Id_PricelistHeader

pl.Id_PricelistHeader = src.Id_PricelistHeader



Ищите предикат в сканировании кластерного индекса PricelistLine



О вообще у вас cross join двух НД

1.

#SalesPrice AS sp
WHERE
COALESCE(sp.WarehouseCode, N'') = COALESCE(@WarehouseCode, N'') AND
sp.CurrencyCode = @CurrencyCode AND
sp.SalesCode = @SalesCode

2.

PricelistLine
WHERE d_PricelistHeader = @Id_PricelistHeader


как вы с этим собираетесь MERGE делать, мне не понятно.
7 авг 17, 12:51    [20705077]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1668
Изменил запрос вот так, теперь предикат в conditions есть:
            MERGE PricelistLine AS pl
            USING
            (
              SELECT
                sp.Id_Article,
                sp.Price,
                sp.AllowDiscount,
                sp.MeasureUnitCode,
                sp.MinimumQuantity,
                ph.Id_PricelistHeader
              FROM
                #SalesPrice AS sp
                JOIN PricelistHeader AS ph
                  ON COALESCE(sp.WarehouseCode, N'') = COALESCE(ph.WarehouseCode, N'') AND
                     sp.CurrencyCode = ph.CurrencyCode AND
                     sp.SalesCode = ph.SalesCode
            ) AS src
            ON pl.Id_PricelistHeader = src.Id_PricelistHeader
            WHEN NOT MATCHED BY TARGET AND src.Id_PricelistHeader = @Id_PricelistHeader THEN
              INSERT
                (Id_PricelistHeader, Id_Article, Price, AllowDiscount, MeasureUnitCode, MinimumQuantity)
              VALUES
                (src.Id_PricelistHeader, src.Id_Article, src.Price, src.AllowDiscount, src.MeasureUnitCode, src.MinimumQuantity)
            WHEN MATCHED THEN
              UPDATE
              SET
                Id_Article = src.Id_Article,
                Price = src.Price,
                AllowDiscount = src.AllowDiscount,
                MeasureUnitCode = src.MeasureUnitCode,
                MinimumQuantity = src.MinimumQuantity
            WHEN NOT MATCHED BY SOURCE AND pl.Id_PricelistHeader = @Id_PricelistHeader THEN
              DELETE;

Однако всеравно у него Estimated Number Of Rows 397 862 000 000 При чем на вход в MERGE JOIN приходит 2 400 000 с обеих сторон.
Зачем он перемножает их, когда это максимум 2 400 000 * 2 строк, в наихудшем раскладе. Или я не понимаю как работает MERGE JOIN?

К сообщению приложен файл. Размер - 22Kb
7 авг 17, 14:13    [20705381]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
msLex
Member

Откуда:
Сообщений: 7730
X-Cite,

у вас Id_PricelistHeader не уникальный ни в source ни в target, как вы по нему собираетесь merge делать?
7 авг 17, 14:30    [20705434]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
лолл
Member

Откуда:
Сообщений: 450
X-Cite,

Сдается мне все дело в

WHEN NOT MATCHED BY SOURCE AND pl.Id_PricelistHeader = @Id_PricelistHeader THEN
DELETE;

Попробуйте закомментировать кусок, план должен поменяться. Дело в том, что из-за этого условия у вас всегда будет полное сканирование таблицы. Выносите удаление в отдельный запрос.
7 авг 17, 14:31    [20705437]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1668
msLex
X-Cite,

у вас Id_PricelistHeader не уникальный ни в source ни в target, как вы по нему собираетесь merge делать?


дадада... что-то меня перекосило...
Я уже сам вышел на это когда просто написал FULL JOIN по тем же условиям и получил 300 млрд записей...
там надо
ON pl.Id_Article = src.Id_Article AND pl.Id_PricelistHeader = @Id_PricelistHeader

Вопрос закрыт... а я никак не мог понять откуда он берет эти 300 млрд записей... Меня переклинело что в таблицах строк, заголовок уникальный и с этой мыслью никак не мог заметить что страшно накосячил....
7 авг 17, 14:41    [20705491]     Ответить | Цитировать Сообщить модератору
 Re: Инструкция MERGE. План  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
Merge умеет и такое
            WITH
            pl AS (
              SELECT
                *
              FROM
                PricelistLine
              WHERE
                Id_PricelistHeader = @Id_PricelistHeader
            ),
            src AS (
              SELECT
                sp.Id_Article,
                sp.Price,
                sp.AllowDiscount,
                sp.MeasureUnitCode,
                sp.MinimumQuantity
              FROM
                PricelistHeader ph
                INNER JOIN #SalesPrice sp ON (
                      COALESCE(sp.WarehouseCode, N'') = COALESCE(ph.WarehouseCode, N'')
                  AND sp.CurrencyCode = ph.CurrencyCode
                  AND sp.SalesCode = ph.SalesCode )
              WHERE
                ph.Id_PricelistHeader = @Id_PricelistHeader
            )
            MERGE
            INTO
              pl
            USING
              src
            ON (
                  pl.Id_Article = src.Id_Article )
            WHEN NOT MATCHED BY TARGET THEN
              INSERT
                (Id_PricelistHeader, Id_Article, Price, AllowDiscount, MeasureUnitCode, MinimumQuantity)
              VALUES
                (@Id_PricelistHeader, src.Id_Article, src.Price, src.AllowDiscount, src.MeasureUnitCode, src.MinimumQuantity)
            WHEN MATCHED THEN
              UPDATE
              SET
                pl.Id_Article = src.Id_Article,
                pl.Price = src.Price,
                pl.AllowDiscount = src.AllowDiscount,
                pl.MeasureUnitCode = src.MeasureUnitCode,
                pl.MinimumQuantity = src.MinimumQuantity
            WHEN NOT MATCHED BY SOURCE THEN
              DELETE;
9 авг 17, 11:10    [20710224]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить