- メモリー展開+ファイル作成
@posts = Post.all open(file_name, "wb") do |f| @posts.each do |post| f.write(post.to_csv + "\r\n") end end send_file(file_name)
長所
簡単
短所
@postsが大量データだった場合に、メモリー不足に陥ります。
ファイルが出来上がるまで応答を返せない。
- フェッチループ+ファイル作成
open(file_name, "wb") do |f| Post.connection.raw_connection.query("select * from posts", :cache_rows => false).each do |row| f.write("#{row[0]},#{row[1]}\r\n") end end send_file(file_name)
長所
同時に必要なメモリーが削減する事ができる。
短所
生SQLを書く必要があり、少しとはいえDB依存のコード(raw connection)を書く必要あり。
ファイルが出来上がるまで応答を返せない。
なおrailsにはbatch方式でのquery発行もありますが、複数回SQLを実行してしまうのでスピード面で問題が出る事が多いです。
- フェッチループ+ネットワーク転送
headers.merge!( "Content-Type" => "application/octet-stream", 'Content-Disposition' => "attachment; filename=\"test.csv\"", 'Content-Transfer-Encoding' => 'binary' ) self.response_body = proc { |r, o| Post.connection.raw_connection.query("select * from posts", :cache_rows => false).each do |row| o.write("#{row[0]},#{row[1]}\r\n") end }
長所
同時に必要なメモリーが削減する事ができる。
途中で応答が返せる(ネットワーク例外を途中で捕捉できるので尚良しです)。
短所
生SQLを書く必要があり、少しとはいえDB依存のコード(raw connection)を書く必要あり。
※webrickでは応答は最後になってしまうので注意
※rails3になってまた変わったみたい。 http://stackoverflow.com/questions/3507594/ruby-on-rails-3-streaming-data-through-rails-to-client
- 結論
要件に応じてメモリー展開+ネットワーク転送(簡単)、もしくは、フェッチループ+ネットワーク転送(無敵)が良いと思う。
2011/01/25 追記
よく考えたらrails3になってArelが導入されたおかげで、sqlは構築するのが楽になりましたね。。
Post.where("created_at < ?", Time.now).to_sql
0 件のコメント:
コメントを投稿