简体   繁体   English

Rails“包含”方法并避免N + 1查询

[英]Rails “includes” Method and Avoiding N+1 Query

I don't understand the Rails includes method as well as I'd like, and I ran into an issue that I'm hoping to clarify. 我不完全了解Rails的includes方法,我遇到了一个我想澄清的问题。 I have a Board model that has_many :members and has_many :lists (and a list has_many :cards ). 我有一个具有has_many :membershas_many :lists董事会模型(还有一个has_many :cards列表)。 In the following boards controller , the show method looks as follows: 在以下板控制器中show方法如下所示:

def show
  @board = Board.includes(:members, lists: :cards).find(params[:id])
  ...
end

Why is the includes method needed here? 为什么这里需要includes方法? Why couldn't we just use @board = Board.find(params[:id]) and then access the members and lists via @board.members and @board.lists ? 为什么我们不能只使用@board = Board.find(params[:id])然后通过@board.members@board.lists访问成员和列表? I guess I'm not really seeing why we would need to prefetch. 我想我不是真的不明白为什么我们需要预取。 It'd be awesome if someone could detail why this is more effective in terms of SQL queries. 如果有人可以详细说明为什么这对SQL查询更有效,那将是非常棒的。 Thanks! 谢谢!

Per the Rails docs: 根据Rails文档:

Eager loading is the mechanism for loading the associated records of the objects returned by Model.find using as few queries as possible. 急切加载是一种使用尽可能少的查询来加载Model.find返回的对象的关联记录的机制。

When you simply load a record and later query its different relationships, you have to run a query each time. 当您简单地加载一条记录并稍后查询其不同的关系时,您每次都必须运行一个查询。 Take this example, also from the Rails docs: 还是从Rails文档中获取以下示例:

clients = Client.limit(10)

clients.each do |client|
  puts client.address.postcode
end

This code executes a database call 11 times to do something pretty trivial, because it has to do each lookup, one at a time. 该代码执行一次数据库调用11次以完成一些琐碎的事情,因为它必须每次都进行一次查找。

Compare the above code to this example: 将上面的代码与此示例进行比较:

clients = Client.includes(:address).limit(10)

clients.each do |client|
  puts client.address.postcode
end 

This code executes a database call 2 times, because all of the necessary associations are included at the onset. 该代码执行两次数据库调用,因为所有必要的关联都包含在开始时。

Here's a link to the pertinent section of the Rails docs. 这是指向Rails文档相关部分的链接。

Extra 额外

A point to note as of recent: if you do a more complex query with an associated model like so: 最近要注意的一点:如果使用类似的关联模型执行更复杂的查询,则:

Board.includes(:members, lists: :cards).where('members.color = ?', 'foo').references(:members)

You need to make sure to include the appended references(:used_eager_loaded_class) to complete the query. 您需要确保包含附加的references(:used_eager_loaded_class)以完成查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM