Мы используем подход, аналогичный тому, который вы описали в нашем продукте для внешних системных входов. (мы обрабатываем пару сотен целевых таблиц, содержащих до 240 столбцов). Как вы описали, существует от 1 до миллиона или более строк.
Как правило, мы не пытаемся настроить одно массовое обновление, мы пытаемся обрабатывать значения одного столбца за раз. Учитывая, что все они представляют собой один тип, представляющий один и тот же элемент данных, промежуточные операторы UPDATE просты. Обычно мы создаем таблицы для сопоставления значений, и это просто
UPDATE target SET target.column = mapping.resultcolumn WHERE target.sourcecolumn = mapping.sourcecolumn.
Настройка отображений немного сложна, но мы снова имеем дело с одним столбцом за раз, делая это.
Я не знаю, как вы определяете «ужасные». Для нас этот процесс выполняется в пакетном режиме, как правило, в одночасье, поэтому абсолютная производительность почти никогда не является проблемой.
EDIT:
Мы также делаем это в пакетах настраиваемого размера, поэтому рабочие наборы и COMMIT никогда не бывают огромными. По умолчанию используется 1000 строк в пакете, но в некоторых конкретных ситуациях было использовано до 40 000 пакетов. Мы также добавляем индексы к рабочим данным для конкретных таблиц.