gpt4 book ai didi

ruby - ActiveRecord 批量? after_commit 产生 O(n) 的麻烦

转载 作者:行者123 更新时间:2023-11-29 13:52:34 26 4
gpt4 key购买 nike

我正在寻找一个好的惯用 rails 模式或 gem 来处理效率低下的 after_commit 模型回调问题。我们希望坚持使用回调来保证数据完整性,但我们希望它运行一次,无论是针对一条记录还是针对包含在事务中的一整批记录。

这是一个用例:

一个投资组合有很多头寸

Position 上有一个 after_commit Hook ,用于根据其在投资组合中的兄弟职位重新计算数字。

直接编辑一个位置就可以了。

但是……

我们现在有一个导入器,可以在一个大的 INSERT 中引入跨越多个投资组合的大量头寸。因此,每次调用此回调都会查询所有 sibling ,并且会为每个 sibling 调用一次 - 因此读取是 O(n**2) 而不是 O(n),写入是 O(n),而它们应该是 O(1)。

为什么不直接将回调放在父投资组合上?”因为在相关更新期间不一定会触及父投资组合。我们不能冒因留下这样的空白而导致的那种不一致状态的风险。

有什么东西可以利用我们在事务中一次提交所有记录这一事实吗?原则上,找出更改了哪些记录应该不难。

一个不错的界面应该是类似于 after_batch_commit 的东西,它可能会提供一个包含所有更改数据或至少包含受影响行的 ID 的轻型对象。

我们的应用中有很多不相关的部分都在寻求这样的解决方案。

最佳答案

一种解决方案是将它们全部插入到一个 SQL 语句中,然后再验证它们。

本文建议了将它们插入单个语句的可能方法。

INSERT multiple records using ruby on rails active record

或者您甚至可以构建 sql 以一次插入数据库中的所有记录。

代码可能是这样的:

max_id = Position.maximum(:id)
Postion.insert_many(data) # not actual code
faulty_positions = Position.where("id > ?", max_id).reject(&:valid?)
remove_and_or_log_faulty_positions(faulty_positions)

这样一来,对于数据中的每 N 个条目,您只需访问数据库 3 次。如果它是大型数据集,那么像您提到的那样分批进行可能会很好。

关于ruby - ActiveRecord 批量? after_commit 产生 O(n) 的麻烦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38189344/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com