简体   繁体   English

使用has_many关系会导致其他MySQL查询吗?

[英]Using a has_many relationship resulting in an additional MySQL query?

I'm going through the Lynda.com course "Ruby on Rails 4 Essential Training". 我正在通过Lynda.com课程“ Ruby on Rails 4基本培训”。 It uses the creation of a simple CMS to teach the framework. 它使用创建一个简单的CMS来教授该框架。 In this CMS, users can create Subjects and Pages . 在此CMS中,用户可以创建SubjectsPages Each Subject has many Pages . 每个Subject都有很多Pages When clicking a link to view the pages that belong to a particular subject, it passes the subject id as a parameter to the Pages controller . 单击链接查看属于特定主题的页面时,它将主题ID作为参数传递给Pages controller The pages controller then does the following to determine which pages to show: 然后,页面控制器执行以下操作以确定要显示的页面:

@subject = Subject.find(params[:subject_id])
@pages = @subject.pages

This simple, makes sense, and results in very understandable code. 这种简单,合理的方法并产生了非常容易理解的代码。 However, it results in an extra DB call by first loading the Subject , and then finding its pages. 但是,通过首先加载Subject ,然后查找其页面,将导致额外的数据库调用。 In the console I see: 在控制台中,我看到:

  Subject Load (0.3ms)  SELECT  `subjects`.* FROM `subjects` WHERE `subjects`.`id` = 3 LIMIT 1
  Page Load (0.3ms)  SELECT `pages`.* FROM `pages` WHERE `pages`.`subject_id` = 3  ORDER BY pages.position ASC

It seems to me that the more efficient approach would be to write something like: 在我看来,更有效的方法是编写如下内容:

@pages = Page.where(subject_id: params[:subject_id])

Indeed, I see only a single SQL query when I do that. 确实,当我这样做时,我只会看到一个SQL查询。 Is it considered best practice to use the first approach, despite the fact that it results in 2 queries? 尽管它导致2个查询,但使用第一种方法是否被认为是最佳实践? Or is that just being used for learning purposes, and ultimately my approach would be considered the better of the two? 还是只是出于学习目的,最终我的方法会被认为是两者中较好的一种?

It depends first whether you need both the @subject and the @pages object. 首先取决于您是否同时需要@subject和@pages对象。 You are right that your proposal is more performant, now this may or may not make a real difference for your user - you'll need profiling to be sure. 没错,您的提案更有效,现在这可能对您的用户没有真正的影响-您需要进行分析以确保。

Finally, it is possible to make a slight change to the tutorial code to make it as performant using 'includes': 最后,可以使用“ includes”对教程代码进行少许更改以使其表现出色:

@subject = Subject.includes(:pages).find(params[:subject_id])
@pages = @subject.pages

This will load everything with a single query. 这将通过单个查询加载所有内容。

如果您不希望使用@subject或基本上是主题记录,则无需使用前者,则可以使用在以后的方法中编写的内容直接访问页面。

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

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