ruby-on-rails - rails : Optimize query N+1 with same table one_to_many and scope conditions

标签 ruby-on-rails ruby postgresql activerecord select-n-plus-1

这是我在使用 Rails 5 时面临的挑战(我使用 Skylight 报告 N+1 查询的服务,他们推荐的解决方案是 here ,但这对我来说还不够)。

我有一个表节点,一个节点可以有多个与之相关的节点(有一列名为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 不会发生。具有 parent_node节点 不再有任何节点

问题是我面临 N+1 的性能问题,因为在原始查询中包含节点是不够的,因为在循环内我使用不同的范围查询每个记录。下面是暴露该问题的示例代码:

# 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

无论如何,这都会触发每个 nd3 变量的 SQL 查询,因为有 another_scope 修改了原始 nds 值,而且我不能包含nds 值中的条件,因为 nd2 需要不满足 another_scope 中条件的节点 .

有没有办法优化这个?

最佳答案

another_scope 替换为 select { |n| n.satisfies_another_scope_criteria? }

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

关于ruby-on-rails - rails : Optimize query N+1 with same table one_to_many and scope conditions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46480973/

相关文章:

ruby-on-rails - rails 5 carrierwave 没有路由匹配图像

Ruby 字符串处理

postgresql - 在docker中运行pgadmin4时CSRF token 错误请求

ruby - lambda vs proc 或 Struct vs Class 区别的正确术语是什么?

sql - 从 WHERE Postgresql 获取数据

sql - 如何使用 Jsonb 从给定日期检索消息?

ruby-on-rails - CarrierWave:上传文件到非云服务器

javascript - js.erb 传递参数错误

ruby-on-rails - 在 ruby​​ worker 中使用 Carrierwave 保存图像

arrays - 从保留索引的数组中删除一个项目