这与一年前的一个问题和变化有关。
我提出了一个应该开箱即用的问题示例,前提是您有可用的 sqlite3:https ://github.com/cairo140/rails-eager-loading-counts-demo
安装说明(用于主分支)
git clone git://github.com/cairo140/rails-eager-loading-counts-demo.git
cd rails-eager-loading-counts-demo
rails s
我在存储库中有更完整的文章,但我的一般问题是这个。
我怎样才能使 Rails 急切加载计数以最大限度地减少全面的数据库查询?
n+1
每当您#count
在关联上使用时,就会出现问题,尽管在 ActiveRelation 中包含了该关联#includes(:associated)
。一种解决方法是使用#length
,但这仅在它被调用的对象已经加载时才有效,更不用说我怀疑它复制了 Rails 内部已经完成的某些事情。此外,使用的一个问题#length
是,当关联开始时没有加载并且计数就是您所需要的时,它会导致不幸的过载。
从自述文件:
我们可以通过在帖子数组上运行#length 来避免这个问题(见附录),它已经加载了,但是如果有随时可用的 count 也是很好的。它不仅更加一致;它提供了不一定需要加载帖子的访问路径。例如,如果您有一个无论如何都显示计数的部分,但有一半的时间是在加载帖子的情况下调用该部分,而一半的时间没有加载,您将面临以下情况:
- 使用
#count
- n
COUNT
已加载帖子时的样式查询- n
COUNT
未加载帖子时的样式查询- 使用
#length
- 帖子已加载时零额外查询
- n
*
未加载帖子时的样式查询在这两种选择之间,没有占优的选择。但是修改 #count 以推迟到 #length 或访问以其他方式存储在幕后的长度会很好,这样我们就可以有以下场景:
- 使用修订版
#count
- 帖子已加载时零额外查询
- n
COUNT
未加载帖子时的样式查询
那么这里的正确方法是什么?有没有我忽略的东西(非常非常有可能)?