サーバー上に大きな CSV ファイルがあり、全体をメモリに読み込まずに、ダウンロードしてチャンクで処理したいと考えています。少し工夫した後、私はこれを思いつきました:
require open-uri
open("http://example.com/#{LARGE_CSV_FILE}") do |file|
file.each_slice(50_000) do |fifty_thousand_lines|
MyModel.import fifty_thousand_lines.join
end
end
open-uri
私の理解では、#open
は HTTP GET をラップし、 -like のIO
ような列挙可能なオブジェクトを返します。#each_slice(n)
一度に n 行の配列をブロックに渡します。次に、それらの行を結合して処理します。
これは問題なくインポートされ、OS X の iStat メニューを見ると、Ruby プロセスのメモリ使用量が手に負えないようには見えません。ただし、一度にすべてのファイルをダウンロードしたようです。メモリ使用量を爆発させずにこれを行うにはどうすればよいでしょうか?
Rubyはそれを一時ファイルにダウンロードしてから、ディスクから1行ずつ読み取りますか? open-uri
代わりに、HTTP 接続を抑制し、ブロックがデータのバッチの処理を終了したときにのみ、より多くのデータをダウンロードすると考えていました。
これは、すべてのファイルをメモリにロードせずにファイルをダウンロードして処理する正しい方法ですか?