【问题标题】:Reducing n+1 queries using the Bullet and RSpec gems使用 Bullet 和 RSpec gem 减少 n+1 个查询
【发布时间】:2014-12-02 13:06:17
【问题描述】:
在 RSpec 中使用 Bullet Gem 的有效方法是什么?现在我觉得如果我将它与我当前的单元测试框架一起使用,我会收到很多通知或测试失败,因为测试本身中的 n+1 个查询与我的生产应用程序中发生的事情无关,例如检查价值或关联。因此,修复 n+1 故障不需要在我的控制器或模型上设置任何内容,而是需要在我的测试设置中设置一些内容以不引发该特定错误,并且我发现我的应用程序没有真正的性能改进。
【问题讨论】:
标签:
ruby-on-rails
ruby
rspec
rails-bullet
【解决方案1】:
最有效的方法根本不是。减少测试中的 n+1 个查询可能有一些合法的优势,最明显的是加快整体执行时间。然而,你很有可能要么是testing too much,要么获得的收益不如what is possible。我通常还发现编写额外的代码来帮助支持测试而不是为应用程序的整体价值做出贡献是没有吸引力的。
请允许我提议您的时间的其他用途。仅对您的舒适程度进行绝对最低限度的单元测试。我个人喜欢关注涉及验证相关问题和金钱或其他数学的复杂方法,您可能有不同的优先级。划清界限将腾出大量时间来编写测试套件中最无用和最脆弱的部分,这将占用您大部分的维护预算。
现在,你所有的额外时间都用来做什么?不用担心,我们会为您找到一些事情要做...您可以从编写一些验收测试开始,特别是对于使用您刚刚放弃了一大堆单元测试的对象的区域。现在,您的 n+1 个警告实际上来自与用户点击页面时相同的位置。现在您可以继续删除所有 n+1 个查询。
但是等等!也不要那样做。相反,花更少的时间setting up your relationships to use the touch option。然后,当子对象更新时,父对象也将更新。这到底与 n+1 个查询有什么关系,您可能想知道。看来我们只是在添加查询...
这就是Russian doll caching 的用武之地。添加它并正确测试它会消耗释放的单元测试和 n+1 消除时间(如果你不小心的话,还会消耗一些时间)。好消息是它更加“真实世界”,对模型中微不足道或不相关的实现变化和诸如此类的变化更具弹性,并且对您的应用程序的巨大性能提升远远超过通过急切加载所有内容来消除每个 n+1 查询前面可能已经提供了。您将希望尽可能多地进入嵌套缓存并尽可能延迟地加载所有内容,以充分利用此方法。
n+1 万岁!