use*_*421 5 postgresql ruby-on-rails query-optimization rails-activerecord
我正在创建一个新表,需要使用基于用户帐户(超过几十万)的数据进行回填,并执行以下一次性佣金任务.
我决定要为每2000个用户创建一个大的INSERT字符串并执行该查询.
这是代码大致的样子:
task :backfill_my_new_table => :environment do
inserts = []
User.find_each do |user|
tuple = # form the tuple based on user and user associations like (1, 'foo', 'bar', NULL)
inserts << tuple
end
# At this point, the inserts array is of size at least 20,000
conn = ActiveRecord::Base.connection
inserts.each_slice(2000) do |slice|
sql = "INSERT INTO my_new_table (ref_id, column_a, column_b, column_c) VALUES #{inserts.join(", ")}"
conn.execute(sql)
end
end
Run Code Online (Sandbox Code Playgroud)
所以我想知道,有更好的方法吗?我采取的方法有哪些缺点?我该怎样改进它?如果我没有对inserts数组进行切片并且只执行一个INSERT超过几十万个VALUES元组的单个怎么办?这种方法的缺点是什么?
谢谢!
取决于您使用的 PG 版本,但在大多数情况下将数据批量加载到表中,这已经足够了:
\n\nBEGIN; INSERT ...; INSERT ...; COMMIT;20k 行对于 PG 来说并不是什么大问题,因此一个事务中的 2k 切片插入就可以了,除非涉及一些非常复杂的触发器/检查。PG 手册中有关批量加载的部分也值得阅读。
\n\nUPD:来自depesz 的一篇有点旧但精彩的文章,摘录:
\n\n\n\n因此,如果您想尽快插入数据 \xe2\x80\x93 使用 copy (或者更好的是 \xe2\x80\x93 pgbulkload)。如果出于某种原因你不能使用复制,那么使用多行插入(8.2 中的新功能!)。然后,如果可以的话,将它们捆绑在事务中,并使用准备好的事务,但通常 \xe2\x80\x93 它们不会给你太多。
\n
| 归档时间: |
|
| 查看次数: |
676 次 |
| 最近记录: |