我正在寻找一个好的惯用轨道模式或gem来处理效率低下的after_commit
模型回调问题。我们希望坚持使用回调来保证数据的完整性,但我们希望它能够运行一次,无论是一条记录还是整个事务中包含的整批记录。
以下是一个用例:
Portfolio
有很多positions
。
在Position
上有一个after_commit
钩子,可以参考其投资组合中的兄弟位置重新计算数字。
直接编辑一个位置就好了。
然而...
我们现在有一个进口商可以在一个大的INSERT
中引入许多投资组合。因此,每次调用此回调都会查询所有兄弟,并为每个兄弟调用一次 - 所以读取是O(n ** 2)而不是O(n),写入是O(n),它们应该是O(1)。< / p>
'为什么不将回调放在父组合上?'因为在相关更新期间不一定会触及父级。我们不能冒这种不一致状态的风险,这可能是由于留下这样的空隙所致。
那里有什么可以利用我们在交易中一次提交所有记录的事实吗?原则上,要弄清楚哪些记录发生变化应该不会太难。
一个不错的界面就像after_batch_commit
这样可以提供一个轻量级对象,其中包含所有已更改的数据或至少受影响的行的ID。
我们的应用程序中有很多不相关的部分要求这样的解决方案。
答案 0 :(得分:0)
一种解决方案可能是将它们全部插入一个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个条目触摸数据库三次。如果它是大型数据集,那么你可能会批量生产。