Ruby on rails 如何降低命中率
假设我有十万用户 举个简单的例子Ruby on rails 如何降低命中率,ruby-on-rails,activerecord,rails-activerecord,Ruby On Rails,Activerecord,Rails Activerecord,假设我有十万用户 举个简单的例子 user = User.where(id: 1..10000) User Load (30.8ms) SELECT `users`.* FROM `users` WHERE (`users`.`id` BETWEEN 1 AND 10000) 在这里,我想像这样切 user.where(id: 100..1000) User Load (2.9ms) SELECT `users`.* FROM `users` WHERE (`users`.`id`
user = User.where(id: 1..10000)
User Load (30.8ms) SELECT `users`.* FROM `users` WHERE (`users`.`id` BETWEEN 1 AND 10000)
在这里,我想像这样切
user.where(id: 100..1000)
User Load (2.9ms) SELECT `users`.* FROM `users` WHERE (`users`.`id` BETWEEN 1 AND 10000) AND (`users`.`id` BETWEEN 100 AND 1000)
为什么活动记录两次命中db?它已经有了更大数据的结果。为什么它必须命中db,而不仅仅是重用和切片ActiveRecord::Relation
有什么好的解决方案吗?ActiveRecord跟踪查询并能够缓存某些重复的请求,但在这种情况下,库不能立即理解第二个请求是第一个请求的子集 此外,ActiveRecord这样的通用库可能不希望实现这样的缓存逻辑,原因有几个。在一个非常大的应用程序中缓存一个大数据集可能会导致几Mb的内存,并且进程可能会相当快地达到机器的内存限制,因为垃圾收集器将无法重新收集内存 长话短说,在通用ORM库中实现这样的特性是一个非常糟糕的主意
如果您想在自己的代码中实现它,您可以自由地执行。ActiveRecord两次命中db,因为您在控制台中运行它。这将通过
.inspect
调用每行上的查询。如果这是在一个代码块中运行的,那么调用将被延迟,直到您实际访问user
而不是让两次迭代在一次中通过:
用户。其中(“id介于?和之间?”,1001000)
它将减少数据库命中率,希望这是您问题的答案它不会命中多次..它只是在WHERE中使用两个子句进行单个查询。多么愚蠢的查询-满足WHERE子句的唯一值是100到1000之间的用户ID。我希望这只是一个例子。对于这样一个例子,代码编写者应该确保,如果已经将用户存储在变量中,就不会再次重新加载它们。数据库可以缓存相同查询的结果,但它永远不会缓存两个不同查询的结果,因为它已经“计算”出一个查询是另一个查询的子集。