今回は、railsのバッチ処理でループ処理を実行する際にはfind_each
を使用することをおすすめされたので備忘録として書き留めておきます。
find_eachとは
find_each
とは、配列に対してループ処理を行うeachメソッドの派生版であり、取得するレコードを小分けにしてループ処理を行うことができます。
例えば、articlesテーブルに10,000個のレコードがあるとします。
articles = Article.all
articles.find_each(batch_size: 100) do |article|
article.update!(title: 'article_test')
end
のように書くことによって、「articlesテーブルのtitleカラムの中身を'article_title'にする」というループ処理を、10,000個のレコードを100個ずつ取得し100回に分けて実行することができます。
find_eachとeachの違い
二つのメソッドの違いは単純で、
each
=> 配列全てを一度にループ処理にかける
find_each
=> 配列を分割して順番に(直列処理で)ループ処理にかける
となります。この、直列処理というのが重要になってきます。
find_eachのメリット
find_eachのメリットを理解するためには、CPU
とメモリ
という概念を理解しなければいけません。
CPUとは
CPUとは、コンピュータが制御や演算を行い動作命令を出す、言わば「パソコンの脳みそ」のような存在です。
CPUの性能が良いほど、処理速度が速いということなので複雑な処理もスムーズに行えるということになります。
メモリとは
メモリとは、CPUがデータを処理する際に、その作業データを一時的に保存しておく領域になります。
つまり、CPUの性能が良くても、メモリの容量が少ない場合は大量のデータを扱うような作業ができないというようなことが起こり得ます。
つまり
バッチ処理を行う際、メモリ容量の許容範囲を超えるような大量のデータを扱う場合は、OOM(Out Of Memory)エラーが出てしまうため、工夫が必要となります。
それを解決してくれるのがfind_each
ということになります。前述した通り、find_eachは作業データを指定した単位で分割して直列的に処理してくれるので、OOMにならないように分割単位を設定することで、安全にバッチ処理を実行することができます。
まとめ
大量のデータをバッチで処理する時には、OOMにならないようにデータを分割処理することができるfind_eachメソッドを使おう。