什么是我可以减少的方式。包括关联查询?

时间:2017-07-31 14:41:00

标签: ruby-on-rails

我有一个非常慢的查询,如下所示:

people = includes({ project: [{ best_analysis: :main_language }, :logo] }, :name, name_fact: :primary_language)
               .where(name_id: limit(limit).unclaimed_people(opts))

查看includes方法调用并注意到正在加载大量关联。在RailsSpeed一书中,有以下引用:

  

“例如,请考虑一下:

Car.all.includes(:drivers, { parts: :vendors }, :log_messages)
     

这里可以实例化多少个ActiveRecord对象?

     

答案是:

# Cars * ( avg # drivers/car + avg log messages/car + average parts/car * ( average parts/vendor) )
     

每个eager load都会增加实例化对象的数量,从而减慢查询速度。如果未使用这些对象,则可能会不必要地减慢查询速度。请注意嵌套的eager load(上例中的部件和供应商)如何真正增加实例化对象的数量。

     

小心嵌入您的预期负载,并始终使用类似生产的数据进行测试,看看包含是否真的会加快您的整体性能。“

这本书没有提到可能是一个很好的替代品。所以我的问题是我可以用什么样的技术替代includes

2 个答案:

答案 0 :(得分:0)

在我跳之前回答。我没有看到您对查询使用任何分页或限制,这可能会有很大帮助。

不幸的是,真的没有。如果您在视图中使用所有对象都可以。但是,includes有一个可能的替代品。它非常复杂,但它有时仍然有用:您加入所有需要的表,只选择您使用的字段,别名并将它们作为平面结构访问。

这样的东西

(注意:它使用了arel帮助程序。在使用include ArelHelpers::ArelTable)语法的模型中需要NameFact[:id]

relation.join(name_fact: :primary_language).select(
  NameFact[:id].as('name_fact_id')
  PrimaryLanguage[:language].as('primary_language')
)

我不确定它会对你的情况有效,但这是我所知道的唯一选择。

答案 1 :(得分:0)

I have an extremely slow query that looks like this

有几个可能的原因:

  1. 获取并创建了太多不必要的对象。从您发表评论,看起来并非如此,您需要获取所有正在获取的数据。

  2. 未优化数据库索引。检查查询所用的时间。 Explain生成的查询(检查日志以获取查询或.to_sql)并确保它没有进行表扫描和其他昂贵的操作。