2

这是我面临的一个挑战,使用 Rails 5(我使用报告 N+1 查询的Skylight服务,他们推荐的解决方案在这里,但在我的情况下还不够)。

我有一个表nodes,一个Node可以有几个nodes与之相关的(有一个名为 的列parent_node_id),这使我能够将一个与多个相关联。

class Node < ApplicationRecord
  ...
  belongs_to :parent_node, foreign_key: :parent_node_id, class_name: 'Node', optional: true, inverse_of: :nodes
  has_many :nodes, foreign_key: :parent_node_id, class_name: 'Node'
  ...
end

重要 层次结构的级别最大为 1。这意味着node.nodes.first.node 不会发生 a。node有 a 的Aparent_node没有了nodes

问题是我正面临 N+1 的性能问题,nodes因为在原始查询中包含 是不够的,因为在循环中我用不同的范围查询每条记录。这是一个暴露问题的示例代码:

# In a controller, including nodes so it does not query inside
nds = Node.some_scope.include(:nodes)
nds.each do |nd|
  ...
  # In a model
  # If I loop inside, there's no extra SQL queries, all good
  nd.nodes.each do |nd2|
    ...
  end
  ...
  # In a model
  # Here's the N+1 issue
  nd.nodes.another_scope.each do |nd3|
    ...
  end
  # Returns a value to the controller
  ...
end

无论如何,这将触发每个变量的 SQL 查询,nd3因为another_scope它会修改原始nds值,并且我不能在nds值中包含条件,因为nodes不符合条件another_scopend2.

有没有办法优化这个?

4

1 回答 1

3

替换another_scopeselect { |n| n.satisfies_another_scope_criteria? }

由于您已经获取了所有子项,因此无需再次在数据库中过滤它们,除非limitanother_scope

于 2017-09-29T09:11:02.480 回答