在铁轨中急切加载和延迟加载

时间:2012-04-10 06:53:45

标签: ruby-on-rails ruby-on-rails-3

我对急切加载和延迟加载感到困惑,rails查询的性能有什么不同吗?

有没有办法实现这两种方式?

2 个答案:

答案 0 :(得分:46)

Eager Loading

提高性能的一种方法是减少SQL查询的数量。你可以通过急切加载来实现这一目标。

User.find(:all, :include => :friends)

在这里你只发出两个查询:

1)一个适用于所有用户。

2)一个用户的所有朋友。

Lazy Loading

如果有一个与许多对象相关联的对象,例如用户有很多朋友,并且你想要像在Orkut中那样显示一个列表,那么你可以像朋友一样激活多个查询,再加上一个用于对象本身的查询。

users = User.find(:all)

然后查询每个用户朋友,例如:

users.each do |user|
  friend = Friend.find_by_user_id(user.id)
end

这里

1)针对所有用户的一个查询。

2)N查询N号。用户朋友。

看看:Rails 3: Lazy loading versus eager loading

希望能帮助你理解这一点。

答案 1 :(得分:15)

急切加载

加载你的枪(就像在维克斯堡一样),等到你真的需要使用它。这是一种急切加载的政策。

亲:是的,一切都准备好了。

Con:你正在耗尽空间/内存。

延迟加载

一名年轻的海军军校学员问纳尔逊勋爵为什么不准备他的船只:

“我不会提前加载我的枪......我只需要1微秒就可以加载它。”他说。 这是一项延迟加载政策。

延迟加载专业版:在您需要之前,您不会访问数据库。

Con:你将会在数据库上打N + 1次.....除非你选择了你想要的列并且你将它别名。 e.g。

@products = Product.order("categories.name").joins(:category)

使用延迟加载策略仅访问数据库一次:

当您在视图模板中调用product.category.name时,上述查询会在数据库中触发N + 1次 - 其中product是@products关系中的单个对象。但如果您使用别名,只需一个查询即可完成所有操作:

@products = Product.order("categories.name").joins(:category).select("products.*, categories.name as category_name")

并像这样使用:product.category_name