44

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

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

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

4

4 回答 4

65

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
于 2013-04-03T10:53:23.550 回答
21

在@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 的解决方案就更有意义了:)

于 2013-04-04T09:04:03.627 回答
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)
于 2013-04-03T10:14:55.987 回答
0

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

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

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

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

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

于 2013-04-03T10:28:08.157 回答