ActiveRecord объем данных, память растет вечно - PullRequest
4 голосов
/ 30 декабря 2011

Я использую ActiveRecord для массовой миграции некоторых данных из таблицы в одной базе данных в другую таблицу в другой базе данных. Около 4 миллионов строк.

Я использую find_each для получения пакетов. Затем я делаю небольшую логику для каждой выбранной записи и записываю ее в другую базу данных. Я пробовал как писать напрямую по одному, так и использовать красивый активный камень записи-записи для пакетной записи.

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

Есть идеи? Кэширует ли ActiveRecord что-то, что я могу отключить?

обновление 17 января 2012

Я думаю, что собираюсь отказаться от этого. Я пытался: * Убедитесь, что все обернуто в ActiveRecord::Base.uncached do * Добавление ActiveRecord::IdentityMap.enabled = falseдумаю , что должно отключить карту идентификации для текущего потока, хотя это не ясно задокументировано, и я думаю карта идентификации не включена по умолчанию в любом случае в Rails)

Кажется, что ни один из них не имеет большого эффекта, память все еще протекает.

Затем я добавил периодическое явное:

  • GC.start

Это, кажется, замедляет скорость утечки памяти, но утечка памяти все еще происходит (в конечном итоге исчерпывает всю память и бомбардировки).

Так что я думаю, что я сдаюсь, и решил, что в настоящее время невозможно использовать AR для чтения миллионов строк из одного БД и вставки их в другой. Возможно, имеется утечка памяти в используемом специфическом для MySQL коде (это мой db), или где-то еще в AR, или кто знает.

Ответы [ 2 ]

1 голос
/ 13 июня 2012

Я бы предложил поставить каждую единицу работы в очередь Resque . Я обнаружил, что у ruby ​​есть некоторые причуды при переборе больших массивов, подобных этим.

Иметь один основной поток, который ставит в очередь работу по идентификатору, а затем несколько рабочих-резервистов, попадающих в эту очередь для выполнения работы.

Я использовал этот метод для записей около 300 тыс., Поэтому он, скорее всего, будет масштабироваться до миллионов.

0 голосов
/ 13 июня 2012

Измените строку # 86 на bulk_queue = [], так как bulk_queue.clear только устанавливает длину арры на 0, делая невозможным очистку GC.

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