Когда мне приходилось выполнять такую работу раньше, я выкидывал ссылки на SQL и освежал свои мысли о том, как выполнять сложные обновления. Обычно вы можете сделать много коротких обновлений с хорошим запросом. Кроме того, вы сможете найти прямую помощь с запросом (опубликуйте свою схему и начните запросы в гисте, если они действительно огромны)
Мне недавно пришлось заполнить значение counter_cache, и перед тем, как сделать это в виде набора кода ruby, загружающего родителей и подсчитывающего их детей, я дал этому запросу шанс:
UPDATE rates r SET children_count = child_counts.my_count from (SELECT parent_id, count(*) as my_count FROM rates GROUP BY parent_id having parent_id is not null) as child_counts where child_counts.parent_id = r.id;
, который обновил 200 тыс. Строк всего за несколько секунд
Если вы не можете сделать это в одном запросе, и если это одноразовая операция, вы можете разбить ваш процесс на 2 шага. Сначала сделайте тяжелую работу и сохраните результаты в новой таблице, затем прочитайте из этой таблицы и сделайте окончательное обновление. В последнее время мне пришлось провести массивное агрегирование данных, и все тяжелые работы заняли 2 дня обработки и расчетов. Результат был помещен в новую таблицу с идентификатором соответствующей строки и итоговой суммой. В процессе производства у меня был быстрый скрипт, который считывал из этой новой таблицы и обновлял соответствующие строки. Это также позволило мне остановиться и перезапустить с того места, где я остановился, и предварительно проверить результаты перед обновлением продукта. Кроме того, это сделало обновление продукта очень быстрым.
При этом я также узнал, что важно выполнять вашу работу в пакетном режиме, если вы можете, и фиксировать транзакцию настолько часто, насколько это возможно / безопасно, чтобы вы не держались за большую транзакцию слишком долго.