【发布时间】:2014-07-17 05:34:26
【问题描述】:
老板想要每个商家的顺序订单号,从 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 专家,但有没有办法在每个 Mercer_id 上使用 999+row_number() 的窗口函数并将该 row_number 保存回 order_seq 列?
编辑:
使用@Gorden-Linoff 回答,但稍作修改。我意识到我不需要在 Mercer_id 上使用分区,因为只有一些活跃的商家需要这个,而不是整个表。另外更新需要在orders表上,而不是在merchans表上,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 个商家。
【问题讨论】:
标签: sql ruby-on-rails postgresql