我有一个非常慢的查询,如下所示:
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
?
答案 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
有几个可能的原因:
获取并创建了太多不必要的对象。从您发表评论,看起来并非如此,您需要获取所有正在获取的数据。
未优化数据库索引。检查查询所用的时间。 Explain
生成的查询(检查日志以获取查询或.to_sql
)并确保它没有进行表扫描和其他昂贵的操作。