Как разбить длинную миграцию данных на несколько транзакций?
Есть БД, где одна табличка занимает очень много места на диске.
Я добавил к ней новый столбец.
Теперь нужно заполнить его.
Т.к. миграция выполняется в транзакции и затронет почти все записи, то это будет долго и, предполагаю, размер таблицы под конец транзакции увеличится в ~2 раза (из-за MVCC).
При этом мне не нужно выполнять эти изменения в одной транзакции, но нужно выполнить в одной миграции. Как это сделать?
update t t1 set new_column = 'value'
from (select id from t where new_column is null limit 100000) t2
where t1.id = t2.id
Выполнять пока не вернет 0 строк affected. Делаете нужные интервалы между запросами, чтобы вакуум успевал. Limit можно больше, например миллион, если таблица не очень нагружена писателями
Melkij, покурил доку и сделал внетранзакционную миграцию (atomic=False), где теперь заполняю колонку небольшими порциями. Melkij, похоже именно вы меня и поняли, что всё это затевалось не только из-за ограничения RAM, но и из-за нежелания раздувать таблицу в 2 раза (обновляя почти всю колонку в одной транзакции я бы создал по одному tuple для каждой строки из-за MVCC, и удаляться устаревшие tuple стали бы не ранее завершения миграции=транзакции)
Вы упомянули vacuum. Его я не вызываю между делом и полагал, что postgres сам вовремя подсуитится. По-вашему зря надеюсь на автоматику? Через сколько обновленных строк вы порекомендуете вызывать vacuum?
wawa, у меня нет сейчас особого желания выяснять, настроили ли вы автовакуум должным образом (да и включен ли он у вас, а то бывают ненормальные выключающие автовакуум). Поэтому и упомянул вакуум как гарант своевременного прохода вакуума по табличке. Впрочем, не гарантирующий очищение старых версий строк, вдруг у вас ещё вагон долгих транзакций висят (включая реплики с hot standby feedback).
На адекватно-аггрессивных настройках автовакуума достаточно задержки между итерациями примерно в удвоенное время выполнения одной транзакции обновления чтобы не аффектить ни мастер ни реплики и для работы автовакуума быть достаточным.
На неясно каких настройках - штук 10 вызовов вакуума на табличку не помешают.