为何我的ActiveRecord查询未合并执行而是分开执行?
问题分析与解决方案
问题原因
你遇到的分开执行情况是正常的,根源出在代码里的self.orders.ids调用:
ids方法会立即触发SQL查询,把当前对象关联的订单ID一次性加载到内存中- 后续的
Summary.where会以这些内存中的ID作为参数,生成独立的SQL查询获取Summary的ID - 最后才执行Order的查询,导致整个逻辑拆分成了多步SQL请求
而控制台里看到的单条嵌套查询,大概率是测试时的特殊情况(比如控制台的预编译展示),实际运行时ids的即时查询会打破嵌套结构。
解决方法:改用子查询替代ids
把self.orders.ids替换为self.orders.select(:id),这样整个查询会保持嵌套结构,不会提前执行任何子查询,最终生成单条SQL:
Order.where( summary_id: Summary.where( association_table: Invoice.table_name, association_column: 'invoice_id', association_value: self.orders.select(:id) # 替换ids为select(:id) ).select(:id), status: :pending ).find_each { |order| order.process }
修改后生成的完整嵌套SQL如下:
SELECT orders.* FROM orders WHERE orders.summary_id IN ( SELECT summaries.id FROM summaries WHERE summaries.association_table = 'invoices' AND summaries.association_column = 'invoice_id' AND summaries.association_value IN (SELECT id FROM orders WHERE ...) ) AND orders.status = 1
这样就能确保所有逻辑合并为单条SQL查询,避免多次数据库请求。
内容的提问来源于stack exchange,提问作者Kuri
相关产品推荐
相关产品推荐

