#mysql #ruby-on-rails #ruby
#mysql #ruby-on-rails #ruby
Вопрос:
Каков наилучший способ выполнить массовое обновление всех записей в большой таблице в MySQL?
Во время процесса очистки мы обновляем все строки в таблице users, которая содержит 28 миллионов строк, чтобы замаскировать несколько столбцов. В настоящее время для выполнения задачи rake требуется около 2 часов, а срок действия сеанса AWS также составляет 2 часа. Если задача rake занимает больше времени, чем истечение сеанса, сборка завершится неудачно.
Из-за большого количества записей мы обновляем 25 тысяч строк одновременно, используя find_in_batches, а затем update_all в результатах. Мы переключаемся между каждой партией, отключаясь на 0,1 с, чтобы избежать перегрузки процессора.
Итак, вопрос в том, можем ли мы каким-либо образом оптимизировать массовое обновление дальше или увеличить срок действия сеанса AWS до 3 часов?
Одним из вариантов может быть пакетирование по диапазонам идентификаторов, а не по точным размерам пакета. Итак, обновите между идентификатором 1-100000, затем 100001-200000 и так далее. Это позволяет избежать передачи больших наборов идентификаторов. Поскольку в идентификаторах будут пробелы, каждый пакет будет разного размера, но это может не быть проблемой.
Спасибо за ваш вклад.
Комментарии:
1. Что было бы не так с простым старым добрым SQL-запросом для обновления всего сразу? Это должно значительно сократить время обновления.
2. Вы должны опубликовать здесь структуру таблицы и запрос на обновление, тогда мы сможем дать совет.
Ответ №1:
Для таких больших обновлений накладные расходы на выборку записей и создание экземпляров объектов AR очень значительны (а также будет замедление из-за GC), самый быстрый способ выполнить — это написать необработанный SQL-запрос, который выполнит обновление (или использовать update_all
для его построения, что очень похоже, но позволяет использовать области / объединения по отношениям).