Rails最好的方式来添加大量的记录

时间:2012-05-02 19:46:50

标签: mysql sql ruby-on-rails

我必须在Rails中一次向数据库添加25000条记录。 我也必须验证它们。

以下是我现在所拥有的:

  # controller create action
  def create
    emails = params[:emails][:list].split("\r\n")
    @created_count = 0
    @rejected_count = 0

    inserts = []
    emails.each do |email|
      @email = Email.new(:email => email)
      if @email.valid?
        @created_count += 1
        inserts.push "('#{email}', '#{Date.today}', '#{Date.today}')"
      else
        @rejected_count += 1
      end
    end
    return if emails.empty?
    sql = "INSERT INTO `emails` (`email`, `updated_at`, `created_at`) VALUES #{inserts.join(", ")}"
    Email.connection.execute(sql) unless inserts.empty?
    redirect_to new_email_path, :notice => "Successfuly created #{@created_count} emails, rejected #{@rejected_count}"
  end

现在非常慢,无法添加此类记录的超时原因。

有什么想法吗?我正在使用mysql。

3 个答案:

答案 0 :(得分:2)

我想到了三件事:

  1. 您可以使用以下适当的工具来帮助自己: zdennis/activerecord-importjsuchal/activerecord-fast-import。问题在于,您的示例是,您还将创建25000个对象。如果您告诉activerecord-import不使用验证,则不会创建新对象(activerecord-import/wiki/Benchmarks
  2. 将数万行导入关系数据库永远不会超快,它应该通过后台进程异步完成。还有一些工具,如DelayedJob等:https://www.ruby-toolbox.com/
  3. 将属于model的代码移出controller(TM)
  4. 之后,您需要重新考虑这部分应用程序的流程。如果您在create等控制器操作中使用后台处理,则不能只返回HTTP 201HTTP 200。您需要做的是返回“快速”HTTP 202 Accepted,并提供指向另一个表示的链接,用户可以检查其请求的状态(我们是否已经成功响应?有多少封电子邮件失败?),因为它现在正在后台处理。 它听起来有点复杂,这是一个标志,你可能不应该这样做。为什么你必须在一个请求中添加25000条记录?什么是backgorund?

答案 1 :(得分:0)

为什么不为工作创建rake任务?以下链接很好地解释了它。

http://www.ultrasaurus.com/sarahblog/2009/12/creating-a-custom-rake-task/

简而言之,一旦你编写了rake任务,就可以通过以下方式开始工作:

rake member:load_emails

答案 2 :(得分:0)

如果您关注速度,我会从另一个角度解决问题。

  • 创建一个复制emails表结构的表格;让它为emails_copy。不要复制索引和约束。
  • 使用数据库的快速导入工具将25k记录导入其中。请查阅您的DB文档或查看例如MySQL的this answer。您将不得不准备输入文件,但这样做的速度更快 - 我想您已经以某种文本或表格形式获得了数据。
  • emails_copy创建索引和约束以模仿emails表。违规行为(如有)将浮出水面;解决它们。
  • 验证表格内的数据。可能需要一些原始SQL语句来检查严重错误。 You don't have to validate emails for anything but very simple format anyway。也许您可以针对您将用于导入的文本进行所有验证。
  • insert into emails select * from emails_copy将电子邮件放入生产表。好吧,您可以使用它来获得正确的自动增量ID。
  • 一旦您肯定该流程成功,drop table emails_copy