Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何在Rails中回填新表?_Ruby On Rails_Postgresql_Query Optimization_Rails Activerecord - Fatal编程技术网

Ruby on rails 如何在Rails中回填新表?

Ruby on rails 如何在Rails中回填新表?,ruby-on-rails,postgresql,query-optimization,rails-activerecord,Ruby On Rails,Postgresql,Query Optimization,Rails Activerecord,我正在创建一个新表,该表需要使用基于用户帐户(超过几十个)的数据进行回填,并执行以下一次性rake任务 我决定为每2000个用户创建一个大的插入字符串,并执行该查询 下面是代码的大致外观: task :backfill_my_new_table => :environment do inserts = [] User.find_each do |user| tuple = # form the tuple based on user and user ass

我正在创建一个新表,该表需要使用基于用户帐户(超过几十个)的数据进行回填,并执行以下一次性rake任务

我决定为每2000个用户创建一个大的插入字符串,并执行该查询

下面是代码的大致外观:

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
task:backfill\u my\u new\u table=>:environment do
插入=[]
User.find_每个do|用户|
tuple=#根据用户和用户关联形成tuple,如(1,'foo','bar',NULL)

插入取决于您使用的PG版本,但在大多数情况下,将数据批量加载到表中就足够了:

  • 尽可能使用而不是插入
  • 如果使用多个插入,请禁用自动提交并在单个事务中包装所有插入,即
    BEGIN;插入。。。;插入。。。;承诺
  • 禁用目标表的索引和检查/约束
  • 禁用表触发器
  • 所以它变成了(从第9.5页开始,别忘了在数据导入后打开日志记录),或者增加了,所以不会被淹没
20k行对于PG来说并不是什么大问题,因此在一个事务中插入2k个切片就可以了,除非涉及一些非常复杂的触发器/检查。它也值得一读

UPD:和,摘录:

因此,如果您希望尽可能快地插入数据,请使用copy(或者更好的是使用pgbulkload)。如果出于任何原因不能使用“复制”,则使用多行插入(8.2中新增!)。然后,如果可以,将它们捆绑到事务中,并使用准备好的事务,但一般来说,它们不会给您带来太多


为什么不使用事务中包装的MyNewTable方法来加速插入?另外,当前的实现为SQL注入打开了大门。哦,我错过了您同时进行多个插入的机会。这确实会更快(但如果在一个1000个事务中包装普通插入,则不确定速度有多快)。