0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rails】eachメソッドに関して調べた事。eachメソッドの問題点とその対策

Posted at

csvファイルのインポート機能を実装している際に生じた疑問が今回のお題です。
備忘録として記述しております。

eachメソッド

eachは、配列の要素ひとつひとつに対して、配列の要素の数だけ繰り返し処理が行えるメソッドです。

eachメソッドの問題点

DBやファイルからデータを取得してきて処理をしたい場合、
eachメソッドで処理しようとすると対象データがすべてメモリに展開されてしまうのだそうです。

【出力時の対策】find_each や find_in_batchesを使う。

find_eachメソッドは1行ずつメモリに展開していくので、
レコード数を気にせず処理をすることができるそうなのです!

Stock.each do |stock|
  # 処理
end

こちらを・・・

Stock.find_each do |stock|
  # 処理
end

に変更です!
さらにさらに、find_in_batchesメソッドだと取得したデータを配列でまとめて処理してくれるそうです!
デフォルトで1000件(!)ずつ処理してくれて
batch_sizeオプションで何件ずつ処理するかの指定もできちゃうそうです!

Stock.find_in_batches(batch_size: 500) do |stocks|
  # 処理
end

ちなみに、batchはバッチと読んで「一束、一団、1回分、ひとまとまり」と言う意味で
まとめてしないさいな!って事ですね。

【入力時の対策】foreachを使用する

私がインポートしようとしているcsvファイルで4~500行ぐらいですが
数千行、数万行にも及ぶcsvファイルを一度に展開してしまうと鬼の如くメモリを消費してしまいます。
(数万行ってなんすか、おっかねぇ・・・)
対策として、foreachを使って1行ずつ展開してメモリを節約します。素晴らしい!

stocks = CSV.read('tmp/stock_data.csv') # 一度に展開されてしまう
users.each do |row|
  # 処理
end

こいつが・・・

CSV.foreach('tmp/stock_data.csv') do |row| # 1行ずつ展開してメモリ節約!
  # 処理
end

こうだ!
素晴らしいですね。考えついた人・形にした人は神様に思えます。

参考にさせていただいたサイト様

https://techblog.lclco.com/entry/2019/07/31/180000
ありがとうございます!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?