Сценарий
У нас есть довольно стандартный процесс импорта данных, в котором мы загружаем
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.
