Сценарий
У нас есть довольно стандартный процесс импорта данных, в котором мы загружаем
staging
, затем MERGE
в таблицу target
.
Новые требования (зеленый) включают захват подмножества импортированных данных
в отдельную таблицу queue
для полностью несвязанной обработки.
"Задача"
(1) Подмножество состоит из набора записей: те, которые были
только что вставлен в таблицу target
.
(2) Подмножество является проекцией некоторых вставленных столбцов, но также
по крайней мере, один столбец, который присутствует только в источнике (staging
таблицу).
(3) Оператор MERGE
уже использует предложение OUTPUT..INTO
строго записать $action
, взятый на MERGE
, чтобы мы могли
PIVOT
результат и COUNT
количество вставок, обновлений и
исключений для целей статистики. Нам действительно не нравится буферизация
действия для всего набора данных, подобные этому, и предпочли бы агрегировать
суммы на лету. Излишне говорить, что мы не хотим добавлять больше данных для
это таблица OUTPUT
.
(4) Мы не хотим выполнять соответствующую работу, чтобы MERGE
второй раз по какой-либо причине, даже частично.
target
таблица действительно большая, мы не можем индексировать все, и
операция обычно довольно дорога (минуты, а не секунды).
(5) Мы не рассматриваем возможность округления любых результатов от MERGE
до
клиент, чтобы клиент мог перенаправить его на queue
на
немедленно отправив его обратно. Данные должны оставаться на сервере.
(6) Мы хотим избежать буферизации всего набора данных во временном хранилище
между staging
и queue
.
Каким будет лучший способ этого?
Неудачи
(a) Требование о регистрации только вставленных записей предотвращает нас
от ориентации таблицы queue
непосредственно в предложении OUTPUT..INTO
MERGE
, поскольку это не допускает предложения WHERE
. Мы можем использовать некоторые
CASE
обман, чтобы отметить нежелательные записи для последующего удаления
из queue
без обработки, но это кажется сумасшедшим.
(b) Поскольку некоторые столбцы, предназначенные для queue
, не отображаются в
target
, мы не можем просто добавить триггер ввода в цель
таблицу для загрузки queue
. "Расщепление потока данных" должно произойти раньше.
(c) Поскольку мы уже использовали предложение OUTPUT..INTO
в MERGE
, мы
не может добавить второе предложение OUTPUT
и вставить MERGE
в
INSERT..SELECT
, чтобы загрузить очередь. Это позор, потому что это
чувствует себя как совершенно произвольное ограничение для того, что работает
очень хорошо в противном случае; SELECT
фильтрует только записи с
$action
мы хотим (INSERT
) и INSERT
их в queue
в одном
выражение. Таким образом, СУБД теоретически может избежать буферизации всего
dataset и просто поместите его в queue
. (Примечание: мы не преследовали
и, вероятно, это фактически не оптимизировало план таким образом.)
Ситуация
Мы чувствуем, что исчерпали наши возможности, но решили обратиться к hivemind быть уверенным. Все, что мы можем придумать, это:
(S1) Создайте таблицу VIEW
таблицы target
, которая также содержит значение NULL
столбцы для данных, предназначенных только для queue
, и
Оператор SELECT
определяет их как NULL
. Затем установите INSTEAD OF
триггеры, которые заполняют таблицу target
и queue
соответственно. Наконец, подключите MERGE
, чтобы настроить таргетинг на представление. Эта
работает, но мы не поклонники конструкции - это определенно
выглядит сложнее.
(S2) Откажитесь, буферизируйте весь набор данных во временной таблице, используя
другой MERGE..OUTPUT
. После MERGE
немедленно скопируйте данные
(снова!) из временной таблицы в queue
.