Rails 3的拒绝贪婪加载 [英] Rails 3 refuses to eager load
问题描述
我在工作中的Rails 3.0.7。
I'm working in Rails 3.0.7.
我有不贪婪加载一些多到很多,有一种人对一对多关联。
I have some many-to-many and some one-to-many associations that fail to eager load.
我的联想是:
Person has_many :friends
Person has_many :locations through=> :location_histories
Location belongs_to :location_hour
Location_hour has_many :locations
在我的控制器我有以下几点:
In my controller I have the following:
@people = Person.includes([[:locations=>:location_hour],:friends]).where("(location_histories.current = true) AND (people.name LIKE ? OR friends.first_name LIKE ? OR friends.last_name LIKE ? OR (friends.first_name LIKE ? AND friends.last_name LIKE ?))").limit(10).all
然后,在我看来,我有:
Then in my view I have:
<% @people.each do |person| %>
<tr>
<td><%= link_to person.name, person %></td>
<td><%= link_to person.friends.collect {|s| [s.full_name]}.join(", "), person.friends.first %></td>
<td><%= link_to person.locations.current.first.name, person.locations.current.first %></td>
</tr>
<% end %>
locations.current是一个范围定义为:
locations.current is a scope defined as:
scope :current, lambda {
where("location_histories.current = ?", true)
}
这工作正常,并第一次产生2数据库调用:一个拿到个人ID列表再大的数据库调用的一切是正确连接。问题是,后面有n个沿路线数据库调用
This works as expected and first generates 2 database calls: one to get a list of person ids and then a big database call where everything is properly joined. THE PROBLEM is that after that there are n database calls along the lines of:
SELECT 'friends'.* from 'friends' WHERE ('friends'.person_id = 12345)
因此,对于在视图中循环的每次迭代。不用说,这需要一段时间。
So for each iteration of the loop in the view. Needless to say this takes a while.
我以为。所有会迫使立即加载。任何人有一个想法是怎么回事?
这对ActiveRecord的花费超过3秒。太长了。
I thought that .all would force eager loading. Anyone have an idea what's going on here?
This spends over 3 seconds on ActiveRecord. Way too long.
我将不胜AP preciate任何和所有的建议。
I would greatly appreciate any and all suggestions.
感谢。
推荐答案
确定。终于解决了。照片 我需要调用两个连接,其中包括。我也不得不删除:从加入locations_current关联。它是由试图创造一些混乱
OK. Finally Solved.
I needed to call both joins and includes. I've also had to remove the :locations_current association from the join. It was creating some chaos by attempting to
... LEFT OUTER JOIN `locations` ON `location_histories`.current = 1 ...
这当然不是一个有效的关联。看来,当前条款是被结转到连接。
Which of course is not a valid association. It seems that the 'current' clause was being carried over into the JOINS.
所以,现在我有以下,它的工作原理。
So now I have the following, which works.
@people = Person.joins([[:locations=>:location_hour],:friends]).includes([[:locations=>:location_hour],:friends]).where("(location_histories.current = true) AND (people.name LIKE ? OR friends.first_name LIKE ? OR friends.last_name LIKE ? OR (friends.first_name LIKE ? AND friends.last_name LIKE ?))")
在摘要:
1)我需要使用两个连接并包括对。而热切加载和适当的跨pretation()条件 -
2)我需要保持与条件(即协会:current_locations)出来的连接第
IN SUMMARY:
1) I needed to use both Joins and Includes for eager loading and proper interpretation of the .while() conditions
2) I needed to keep associations with conditions (i.e. :current_locations) out of the joins clause.
请纠正我,如果这似乎是一个明显的错误给您。它似乎工作,虽然。这使下活动记录时间不到1秒。
Please correct me if this seems like a glaring mistake to you. It seems to work though. This brings down the Active Record time to just under 1 sec.
它是常见的组合联接,包括?
Is it common to combine joins and includes?
谢谢!
这篇关于Rails 3的拒绝贪婪加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!