複数の関連テーブルを結合したActiveRecordを扱う際にはfind_eachを使う


こんにちは。エンジニアの佐藤です。

ユーザ情報とイベントを紐付けたActive recordを抽出するバッチ処理を書いていたのですが、レコード数が増えた結果メモリを使い切って開発環境を一つ落ちました。
メモリを使い切ったバッチ処理はこんな感じ。

テーブル構造

顧客 : 注文 = 1 対 多
注文詳細 : 注文 = 1 対 多

バッチ(一部)

1年以内にログインしたユーザを取得し、かつ購入イベントがある場合にそのイベントデータを抽出

顧客.where(1年以内にログインしたユーザ) each do |顧客|
注文 = 注文.where(顧客_id: 顧客.id)

if 注文.present?
注文.each do |注文|
...

こうして複数の関連テーブルを結合したレコードを用いると(他にもいくつかのテーブルが紐付いている),メモリを使い切ることができます。
よってこのように大量のレコードを処理するには、分割する必要があります。
Railsでは`find_each’です。

説明

分割してレコードを取得して処理する。
デフォルトで1000件ずつ処理をする。

Railsドキュメントより

よってeachをfind_eachに書き換えます。

顧客.where(1年以内に来店した顧客) find_each do |顧客|
注文 = 注文.where(顧客_id: 顧客.id)

if 注文.present?
注文.each do |注文|
...

これでメモリを大量消費することはないでしょう。

まとめ

大量のレコードを処理する際には、分割して処理を行う。

最後に

リンクバルではエンジニアの採用を募集しています。採用はこちら