Выполнение огромных миграций данных в рельсах - PullRequest
7 голосов
/ 28 июля 2011

Я испытываю большие трудности с вычислительной мощностью при переносе больших данных (несколько 100 000 строк).Я разрабатываю сервис, который обрабатывает много данных в рельсах.Наши модели постоянно меняются по мере того, как мы все больше и больше понимаем наш дизайн.Это приводит к большому количеству миграций в нашей базе данных, которая является базой данных Postgres 9.0.Часто эти миграции также включают в себя некоторую миграцию самих данных.Вчера мы выяснили, что нам нужно переместить атрибут «текст» модели в отдельную модель, чтобы этот атрибут больше не был просто атрибутом модели, а вместо этого связывал один со многими.

Моя миграцияВыглядело примерно так:

def self.up
  create_table :car_descriptions do |t|
    t.integer :car_id
    t.text :description

    t.timestamps
  end

  Car.find_each do |car|
    if car.description.present?
      car.descriptions.build :description => car.description
    end
    car.save
  end
  remove_column :cars, :description
end

Теперь проблема в том, что это работает довольно медленно, и еще хуже, если я установлю счетчик и выведу прогресс, я вижу, что миграция выполняетсявсе медленнее и медленнее с течением времени.В моем мониторе активности я вижу, что процесс ruby ​​занимает все больше и больше памяти.

Итак, мой вопрос - есть ли лучший способ выполнить миграцию больших данных, как этот?

1 Ответ

12 голосов
/ 28 июля 2011

Вы не должны использовать ActiveRecord здесь для переноса данных из вашей модели Car в модель CarDescription.Вместо этого вам следует вернуться к запуску raw sql (запустить из миграции).В моей прошлой работе у нас были такие проблемы с огромными данными, и запуск raw sqls привел к гораздо более быстрым миграциям (хотя быстрая была иногда 5-6 часов).Еще одна практика, которую мы разработали через некоторое время после многих горьких испытаний, заключалась в том, что мы всегда копировали нашу базу данных с производства на наш промежуточный сервер и запускали процесс миграции по крайней мере два раза на промежуточной стадии.Мы всегда придумали какой-то процесс (специфичный для миграции), который после этой практики сэкономил много времени.Иногда этот процесс включал удаление вручную некоторых индексов, запуск миграции и повторное создание этих индексов вручную.

В текущем случае sql может выглядеть примерно так:

INSERT INTO car_descriptions(car_id, description) SELECT id, description FROM cars

Надеюсь, вы найдетеэто полезно, дайте мне знать, если я могу что-то добавить к ответу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...