Rails 3的拒绝贪婪加载 [英] Rails 3 refuses to eager load

查看:333
本文介绍了Rails 3的拒绝贪婪加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在工作中的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆