【问题标题】:Batch insertion in rails 3在 rails 3 中批量插入
【发布时间】:2013-03-24 22:32:43
【问题描述】:

我想从我的 Rails 应用程序中将几千条记录批量插入数据库(在我的例子中是 POSTGRES)。

这样做的“Rails 方式”是什么? 快速且正确的方法。

我知道我可以通过属性的字符串连接来创建 SQL 查询,但我想要一个更好的方法。

【问题讨论】:

标签: ruby-on-rails ruby ruby-on-rails-3 activerecord rails-postgresql


【解决方案1】:

ActiveRecord .create 方法支持批量创建。如果数据库不支持该功能,该方法将模拟该功能,如果该功能支持,则使用底层数据库引擎。

只需传递一组选项。

# Create an Array of new objects
User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])

支持块,这是共享属性的常用方式。

# Creating an Array of new objects using a block, where the block is executed for each object:
User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
  u.is_admin = false
end

【讨论】:

  • 可能取决于驱动版本和PG版本。您可以在控制台中尝试一下,看看执行的 SQL 语句。
  • 它似乎正在创建单独的查询。尽管通过交易包围它似乎使它更快。有什么办法可以确保插入单个查询?
  • 目前不确定 PG 驱动是否支持。 bitbucket.org/ged/ruby-pg/pull-request/13
  • 我最终使用了 activerecord-import gem。它似乎可以解决问题:)
  • 这个方法没有任何魔力。它只是遍历数组并在每个单独的哈希上调用creategithub.com/rails/rails/blob/…
【解决方案2】:

在@Simone Carletti和@Sumit Munot的两个回答之后,我终于得出了一个解决方案。

在 postgres 驱动程序支持 ActiveRecord .create 方法的批量插入之前,我想使用activerecord-import gem。它在单个插入语句中进行批量插入。

books = []
10.times do |i| 
    books << Book.new(:name => "book #{i}")
end
Book.import books

在 POSTGRES 中,它会导致单个插入语句。

一旦 postgres 驱动程序在单个插入语句中支持 ActiveRecord .create 方法的批量插入,那么@Simone Carletti 的解决方案就更有意义了:)

【讨论】:

  • 遗憾的是,对于这样一个简单的问题,这仍然是最好的解决方案。 'write raw sql' 解决方案可以工作,并且可能更容易一次性使用,但如果你不止一次这样做,那么这个 gem 是最好的解决方案,不要到处乱用原始 sql(或其他语言)。
  • 它说缺少方法是 postgres-9.4, Ubuntu 14.04, rails 4.2
  • @Anwar:你的 Gemfile 中有gem 'activerecord-import' 吗?这是使用Model#import所必需的。
【解决方案3】:

您可以在 Rails 模型中创建一个脚本,编写查询以插入该脚本 在 Rails 中,您可以使用

运行脚本
rails runner MyModelName.my_method_name

是我在项目中使用的最佳方式。

更新:

我在我的项目中使用以下,但它不适合 sql 注入。 如果您没有在此查询中使用用户输入,它可能对您有用

user_string = " ('a@ao.in','a'), ('b@ao.in','b')"
User.connection.insert("INSERT INTO users (email, name) VALUES"+user_string)

对于多条记录:

new_records = [
  {:column => 'value', :column2 => 'value'}, 
  {:column => 'value', :column2 => 'value'}
]

MyModel.create(new_records)

【讨论】:

  • 我正在寻找类似在单个查询中将 1000 个对象插入数据库的方法。用例:我正在从 facebook 登录用户,并通过一个 DB 调用保存他所有的 facebook 朋友。
  • 这正是我想避免的 :) 看来要么是这种方式,要么是更慢的方式......
  • 您可以使用 g-server 在线程中运行多个查询。它可以帮助你
  • 有趣的文章可能对你有帮助coffeepowered.net/2009/01/23/…
  • 那是我刚开始读的第一篇文章。只是写sql感觉不对:)
【解决方案4】:

您可以使用快速方式或 Rails 方式;)根据我的经验,将批量数据导入 Postgres 的最佳方式是通过 CSV。使用 Postgres 的原生 CSV 导入功能,Rails 方式需要几分钟。

http://www.postgresql.org/docs/9.2/static/sql-copy.html

它甚至会触发数据库触发器并遵守数据库约束。

编辑(在您发表评论后): 明白了。在这种情况下,您已经正确描述了您的两个选项。我以前也遇到过同样的情况,使用 Rails 1000 save 实现它!策略,因为它是最简单的方法,然后将其优化为“附加一个巨大的查询字符串”策略,因为它的性能要好一个数量级。

当然,过早的优化是万恶之源,所以也许可以使用简单的慢速 Rails 方式,并且知道构建一个大查询字符串是一种完全合法的优化技术,但会牺牲可维护性。我觉得你真正的问题是'是否有一种不涉及 1000 个查询的 Railsy 方式? - 不幸的是,答案是否定的。

【讨论】:

  • 我觉得我的问题不清楚。我正在考虑用户使用他的 Facebook 帐户登录的用例,我正在保存他所有的朋友。我预计一次大约有 1000 到 4000 条记录。我想在我的 Rails 应用程序中执行此操作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多