如何避免 N + 1 使用 DataMapper 聚合
如果我有一个 Foo 类型的模型,其中有许多 Bar 类型的子记录,我希望能够显示 Foo 记录列表并显示 Bar 子记录的数量。所以我有类似的问题...
@foos.each do |foo|
puts foo.name
puts foo.bars.count
end
如何避免聚合上的 N+1 问题?换句话说,我不想为每一行创建一个新的 SELECT COUNT(*)...
查询。我可以简单地创建一个 SQL 视图并将其映射到一个新模型,但是有更简单的方法吗?
If I have a model of type Foo that has many child records of type Bar, I'd like to be able to show a list of Foo records and show the number of child Bar records. So I have something like...
@foos.each do |foo|
puts foo.name
puts foo.bars.count
end
How can I avoid the N+1 problem on my aggregates? In other words, I don't want a new SELECT COUNT(*)...
query for each row. I could simply create a SQL view and map it to a new Model, but is there a simpler approach?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
DataMpper 对这些事情变化无常,因此我将给您提供几个尝试的选项,这些选项可能会根据您的实际代码的外观而起作用。
只需将 count 更改为 size,即,puts foo.bars.size。 DM 的策略性预先加载有时可以使用这种方法。
在@foos.each循环之前强制进行急切加载,并将计数更改为大小,例如
在 @foos.each 循环之前发出原始 SQL 查询返回带有 foo id 和 bar 计数的结构,#将它们按食物 id 映射到哈希中,并将它们放入循环中。 (我只需要诉诸这种级别的废话一两次,我建议在它之前摆弄 #1 和 2。)
DataMpper is fickle about these things so I'll give you a couple options to try that may work depending on what your real code looks like.
Just change count to size, i.e., puts foo.bars.size. DM's strategic eager loading can sometimes work with this approach.
Force an eager load before the @foos.each loop, and change count to size, e.g.
Issue a raw SQL query before your @foos.each loop that returns structs with foo ids and bar counts, #map those into a Hash by food id and get them inside the loop. (I've only had to resort to this level of nonsense once or twice, I'd recommend fiddling with #1 and 2 for bit before it.)