如何在rails应用程序中将大型csv文件导入mysql?

时间:2013-10-21 03:15:49

标签: mysql ruby-on-rails csv heroku

我在rails应用程序中将导入csv数据实现到mysql中。我已经使用 CSV.parse 在csv文件中逐行读取并导入到数据库中。这种方式效果很好。


但是,当我部署到Heroku服务器时,每个请求的超时为30秒。如果导入csv文件超过30秒。 Heroku服务器有错误:请求超时 - H12 。有没有人帮我找出导入大型csv文件的最佳方法?现在,我只导入包含70个用户的小型csv。我想导入大型csv包括500 - 1000个用户。这是代码:

导入控制器:

CSV.foreach(params[:file].path, :headers => true) do |row|
  i = i + 1

  if i == 1
    @company = Company.find_or_create_by!(name: row[0])       
  end

  @users = User.find_by(email: row[1])

  if @users
    if @company.id == @users.employee.company_id
      render :status=> 401, :json => {:message=> "Error"}
      return
    else
      render :status=> 401, :json => {:message=> "Error"}
      return
    end
  else
    # User
    # # Generate password
    password = row[2]
    user = User.new(email: row[1])
    user.password = password.downcase
    user.normal_password = password.downcase
    user.skip_confirmation!
    user.save!

    obj = {
      'small'   => 'https://' + ENV['AWS_S3_BUCKET'] + '.s3.amazonaws.com/images/' + 'default-profile-pic_30x30.png',
      'medium'  => 'https://' + ENV['AWS_S3_BUCKET'] + '.s3.amazonaws.com/images/' + 'default-profile-pic_40x40.png'
    }

    employee = Employee.new(user_id: user.id)
    employee.update_attributes(name: row[3], job_title: row[5], gender: row[9], job_location: row[10], group_name: row[11], is_admin: to_bool(row[13]), 
                is_manager: to_bool(row[14]), is_reviewee: to_bool(row[6]), admin_target: row[7], admin_view_target: row[12], department: row[8], 
                company_id: @company.id, avatar: obj.to_json)
    employee.save!

  end
end

我尝试使用gems' activerecord-import'或者' fastercsv'但是' activerecord-import'不行,' fastercsv'不适用于ruby 2.0和rails 4.0

3 个答案:

答案 0 :(得分:2)

在控制器中执行此操作对我来说似乎有点多,特别是因为它阻塞了。你有没有想过把它扔进后台工作?

如果我是你,我会:

  1. 上传文件
  2. 将其作为rake任务在后台解析
  3. 另外,请查看:https://github.com/tilo/smarter_csv

答案 1 :(得分:0)

似乎这些行

if i == 1
  @company = Company.find_or_create_by!(name: row[0])       
end

@users = User.find_by(email: row[1])

在30秒的时间范围内需要大量的计算周期。

我建议您使用 resque delayed_job 将常规转换为Heroku后台进程,或者将例程拆分为 n 请求,如果我们无法在某种程度上优化上面的代码。

希望这有帮助。

答案 2 :(得分:0)

使用delayed_jobsidekiqresque等产品在后台处理您的CSV。如果它适合您的用例,您甚至可以使用guardcron

执行此操作