sql - 如何快速批量更新postgres中的序列号

标签 sql ruby-on-rails postgresql

老板想要每个商家的顺序订单号,从 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

我计划在迁移期间运行它以将所有现有订单设置为根据其 ordered_at 日期填充序列号。我在生产数据库的一个分支上对此进行了测试,每次订单更新平均需要 80 毫秒。有近百万的订单记录,这将导致太多的停机时间。

使用本地 postgres 有更快的方法吗?这将是一次性迁移,需要运行一次并且没有任何其他事情同时发生。

我不是 postgres 专家,但有没有办法在每个 merchant_id 上使用 999+row_number() 来使用窗口函数,并将该 row_number 保存回 order_seq 列?

编辑:

使用@Gorden-Linoff 的回答,但稍作修改。我意识到我不需要对 merchant_id 使用分区,因为只有一些活跃的商家需要这个,而不是整个表。另外更新需要在 orders 表上,而不是 merchants 表上,where 子句可以只使用 id 而不是 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 个商家。

最佳答案

我认为您可以使用可更新的子查询对 native 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 重新开始,则只需使用partition by:

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;

关于sql - 如何快速批量更新postgres中的序列号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24765132/

相关文章:

sql - 如何让SQL Server忽略检查?

sql - 查询检索每小时计数,如果没有则检索零

ruby-on-rails - RSpec 测试运行状况端点,无需 Controller 或操作

ruby-on-rails - undefined method `cookie_value' for .... Impressionist gem

sql - 如何在 PostgreSQL 中验证有效的电子邮件地址?

postgresql - 如何从 Postgresql 目录表中检索 Postgresql 序列缓存值?

mysql同字段值累计和

MySQL - 另一种减少连接数量的方法? - 或简写语法

ruby-on-rails - 无法加载此类文件 - linode 中的 bundler (LoadError)

ruby-on-rails - postgresql rails 中的时间比较