一次调用/查询中创建多个Rails ActiveRecord记录

4
在我的一个Rails应用程序中,有一个AR类,我最终获得了许多新初始化的ActiveRecord对象的数组。我希望能够以高效的方式将它们保存到DB中,最好只需要一个方法调用就能实现。目前,我将它们包装在一个事务内。类似于:
Object.transaction do
  @objects.map(&:save)
end

有没有更有效的解决方案来创建/更新记录数组?
2个回答

7

你做得很对,将所有内容包装到一个事务中,因为这样数据库只会刷新一次并更新索引。

在标准SQL中,不能在单个SQL语句中插入多个对象。MySQL可以做到,但这是非默认设置。我怀疑这样做有很大的性能优势。

如果这段代码确实很关键,你可以异步运行它(通过将其移到后台线程 - 请注意,ActiveRecord和多线程存在问题 - 或者让工作程序执行它)。或者你可以手动生成SQL - AR在执行此操作方面并不非常高效。然而,我只会在这非常关键的情况下才会采用这种方式,并认为这是一种hack方法。


同意。只是需要确保我没有漏掉什么。我还将数据库调用更正为方法调用,因为这是目的。我检查了类方法 update_all,想知道在创建新记录时是否有类似的东西可用。 - cnikolaou
你可以使用像activerecord-import这样的gem来进行批量插入。 - user427390
@Corey:你应该添加一个单独的答案。毕竟,一个单独的宝石可以真正引入许多针对每个数据库的优化到大规模导入中。(尽管我并不确定activerecord-import实际上是否这样做;我想看一些基准测试。) - radiospiel
好的观点 - 既然这是另一种解决方案,我就添加了一个答案 :) - user427390

2

我建议在主线activerecord支持批量插入之前,使用activerecord-import宝石。

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

# 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) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接