【问题标题】:Create multiple Rails ActiveRecord records in one call/query在一次调用/查询中创建多个 Rails ActiveRecord 记录
【发布时间】:2011-06-10 10:03:00
【问题描述】:

在我的一个 Rails 应用程序的 AR 类中,我最终得到了许多新初始化的 ActiveRecord 对象的数组。

我希望能够以一种有效的方式将它们保存到数据库中,理想情况下,在一个方法调用中。目前,我将它们封装在一个事务中。

类似:

Object.transaction do
  @objects.map(&:save)
end

是否有更有效的解决方案来创建/更新记录数组?

【问题讨论】:

    标签: sql ruby-on-rails activerecord


    【解决方案1】:

    将所有内容包装到事务中是正确的,因为这样数据库只会刷新和更新索引一次。

    您不能在标准 SQL 中的单个 SQL 语句中插入多个对象。 MySQL 可以做到这一点,但这是非默认的。我怀疑这会带来巨大的性能优势。

    如果这段代码对时间非常关键,您可以异步运行它(通过将其移动到后台线程 - 注意 ActiveRecord 和多线程存在问题 - 或者让它由工作人员执行。或者您可以生成 SQL手动 - AR 在这样做方面效率不高。但是,只有在非常关键的情况下,我才会那样这样做,然后会认为它是一种 hack。

    【讨论】:

    • 同意。只需要确保我没有遗漏任何东西。我还更正了对方法调用的 DB 调用,因为这是目的。我检查了类方法update_all,想知道在创建新记录时是否有类似的东西可以使用。
    • 您可以使用像 activerecord-import 这样的 gem 来批量插入。
    • @Corey:您应该添加一个单独的答案。毕竟,一个单独的 gem 确实可以在批量导入中引入一些针对每个数据库的优化。 (尽管我不相信 activerecord-import 确实做到了这一点;我想看看它的一些基准。)
    • 好点——添加了一个答案,因为它是一种替代解决方案:)
    【解决方案2】:

    我建议使用activerecord-import gem,直到主线 activerecord 支持批量插入。

    使用起来相当简单,例如批量插入一堆“评分”记录:

    # Example database record/model
    class Rating < ActiveRecord::Base
    
    end
    
    ratings = []
    
    # Create some fake data here..
    100.times do |i|
        ratings << Rating.new({ stars: (rand * 5).to_i }) # random star rating
    end
    
    # Bulk import ratings (single query)
    Rating.import(ratings) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多