Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.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
Sql 如何快速批量更新postgres中的序号_Sql_Ruby On Rails_Postgresql - Fatal编程技术网

Sql 如何快速批量更新postgres中的序号

Sql 如何快速批量更新postgres中的序号,sql,ruby-on-rails,postgresql,Sql,Ruby On Rails,Postgresql,boss希望每个商户都有顺序的订单号,从1000开始 现在,我正在使用ruby遍历每个商家,并更新订单,如下所示: #running all of this in a migration add_column :orders, :order_seq, :integer Merchant.find_each do |merchant| order_seq = 999 merchant.orders.order(:ordered_at).find_each do |order|

boss希望每个商户都有顺序的订单号,从1000开始

现在,我正在使用ruby遍历每个商家,并更新订单,如下所示:

#running all of this in a migration
add_column :orders, :order_seq, :integer


Merchant.find_each do |merchant|
  order_seq = 999
  merchant.orders.order(:ordered_at).find_each do |order|
    order.update_column(:order_seq, order_seq+=1)
  end
end
我计划在迁移过程中运行此程序,以设置所有现有订单,使其按照其在日期的订单号填充序列号。我在fork of the production数据库上测试了这一点,每次订单更新平均需要80毫秒。由于订单记录接近100万条,这将导致太多的停机时间

对于本地博士后,有没有更快的方法?这将是一次迁移,需要运行一次,并且没有其他并发操作

我不是postgres专家,但有没有办法在每个商户id上使用999+行号的窗口功能,并将该行号保存回订单列

编辑:

使用@Gorden Linoff回答,但稍作修改。我意识到我不需要在商户id上使用分区,因为只有一些活动商户需要分区,而不是整个表。此外,更新需要在orders表上,而不是merchants表上,where子句只能使用id not merchant_id和ordered_at

最终解决方案:

  Merchant.active.find_each(batch_size: 100) do |merchant|
    statement = "update orders set order_seq = o.seqnum + 999 " +
      "from (select o.id, row_number() " +
      " over (order by ordered_at) as seqnum from orders o where o.merchant_id = #{merchant.id}" +
      ") o where orders.id = o.id"
    ActiveRecord::Base.connection.execute(statement)
  end

结果是,此操作需要10分钟来处理200个商户。旧方法在1小时内处理了大约10个商户。

我认为您可以使用可更新的子查询对本机Postgres执行此操作:

update merchants
    set order_seq = m.seqnum + 999
    from (select m.*, row_number() over (order by ordered_at) as seqnum
          from merchants m
         ) m
    where merchants.merchant_id = m.merchant_id and
          merchants.ordered_at = m.ordered_at;
编辑:

如果您希望为每个商户id重新开始,则只需使用分区:


不过,我希望每个商户id的序列号从1000开始。似乎此查询应在订单上更新,而不是商户:更新o set o.order_seq=seqnum+999 from select o.*,按订单的行号,as seqnum from orders o,其中商户id=1 o;但这会产生错误:错误:关系o不存在第1行:更新o集合o.order_seq=seqnum+999^@sketchfemme。哎呀。我使用了SQL Server语法,Postgres语法有点不同,两者都使用了类似的from子句进行更新,但细节不同。我接受这一正确答案,尽管我需要做一些调整,尤其是表名。我将编辑我的问题以包含我的最终解决方案
update merchants
    set order_seq = m.seqnum + 999
    from (select m.*, row_number() over (partition by merchant_id
                                         order by ordered_at
                                        ) as seqnum
          from merchants m
         ) m
    where merchants.merchant_id = m.merchant_id and
          merchants.ordered_at = m.ordered_at;