Каков наиболее эффективный способ обновления таблицы во время операции слияния? - PullRequest
4 голосов
/ 26 марта 2012

Как и многие разработчики, я выполняю множество операций слияния с данными, в частности с SQL Server.

Исторически я использовал старый прием: -

1) Выполнение левого соединенияна существующие данные и вставляя что-либо, для чего у меня нет соответствующей записи.

2) После 1), обновляя строки в моей целевой таблице.

Я должен понизить производительностьна 1).Это неизбежно.Однако, на 2), я был довольно расточительным.Вместо того, чтобы просто обновлять материал, который требует обновления, я обновил все, что соответствовал (независимо от того, изменились ли базовые данные или нет).

Оказывается, что SQL Server не слишком умен для такого рода обновлений,Он не выполняет предварительной проверки, чтобы определить, что то, что вы собираетесь обновить, отличается от того, что вы используете для его обновления.Следовательно, обновления, выполняемые в этом направлении, приводят к физической записи и влияют на все индексы, которые ссылаются на поле.

Итак, из моего POV я могу выбрать следующие варианты: -

1) Продолжитькак обычно, купаясь в текущей расточительности моей рутины (и ежедневно обновляя индексы на больших БД)

  • Плюсы: это просто.
  • Минусы: это дерьмо.

2) Напишите больше операторов UPDATE, которые обновляют определенное поле, если поле изменилось.

Например,

UPDATE
    p2 
SET
    [SpecificField] = p1.[SpecificField]
FROM
    @source p1,
    Dest p2
WHERE
    p2.ExternalKey = p1.ExternalKey
AND COALESCE(p1.[SpecificField],'') <> COALESCE(p2.[SpecificField],'')
  • Плюсы: это очень специфично, обновляется только притребуется обновление.
  • Минусы: множество различных операторов обновления для таблиц с большим количеством столбцов.

3) Что-то бесконечно лучше, чем предлагает сообщество переполнения стека.

Я бы очень хотел пойти с 3).Мои варианты действительно ограничены 1 или 2?Заметка.Я посмотрел в MERGE INTO.Те же проблемы, правда.

1 Ответ

2 голосов
/ 26 марта 2012

С MERGE INTO у вас есть возможность добавить дополнительное условие поиска к предложению WHEN (NOT) MATCHED. Например,

MERGE INTO table_to_upsert AS target
 USING source_table    AS source
    ON target.key1 = source.key1
   AND target.key2 = source.key2
   AND target.key3 = source.key3
WHEN MATCHED AND (target.value <> source.value) THEN
            UPDATE SET target.value     = source.value,
                       target.timestamp = source.timestamp
WHEN MATCHED AND (target.userid <> source.userid) THEN
            UPDATE SET target.userid    = source.userid,
                       target.timestamp = source.timestamp
WHEN NOT MATCHED THEN
            INSERT (key1, key2, key3, 
                    value, userid, timestamp)
            VALUES (source.key1, source.key2, source.key3,
                    source.value, source.userid, source.timestamp)

Однако это не решит вашу проблему, если одновременно обновлять несколько столбцов, MERGE займет первое WHEN (NOT) MATCHED, которое оценивает значение true (аналогично CASE утверждению).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...