Rails - 为什么LINK_To会对数据库产生不必要的命中?

时间:2010-12-14 23:47:21

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

我有以下代码:

<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>

<%= link_to 'Image Set', project_photo_album_path(storyitem.project, @photos.first.photo_album_id) %>

在我的日志中,我看到了:

Photo Load (0.4ms)  SELECT "photos".* FROM "photos" WHERE ("photos"."photo_album_id" = 72) ORDER BY photos.created_at DESC, photos.version DESC LIMIT 1
Photo Load (0.7ms)  SELECT "photos".* FROM "photos" WHERE ("photos"."photo_album_id" = 72) ORDER BY photos.created_at DESC, photos.version DESC LIMIT 4

调试之后,即使4个记录的第一个匹配找到了link_to所需的第一个查询,它就是生成额外数据库命中的link_to。

有没有办法防止此查询多次命中数据库2次。我只想获得限制4的查询,这应该为应用程序提供所需的所有信息。

思想?

更新

我也希望能够输出以下内容:

<%=  @photos.first.photo_album.title %>

但是这也会再次击中数据库。对于上述所有方法,只能为数据库命中一次? thxs

2 个答案:

答案 0 :(得分:1)

我相信第一次点击会在您展示的内容之前发生在代码中。

您确定

行吗?
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>

点击数据库?由于延迟加载,我认为只有在运行第二行时,数据库才会被命中。

我认为你需要做更多调试才能看到第一个数据库命中的位置。

至于您的更新,请将第一行更改为

<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).includes(:photo_albums) %>

在同一查询中加载相册。

答案 1 :(得分:1)

在你的情况下,

<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>

返回一个ActiveRecord::Relation对象,在你调用enumerable方法之前它不会命中。或者,您可以在其上调用firstalllast。这是在你的第二行完成的,

<%= link_to 'Image Set', project_photo_album_path(storyitem.project, @photos.first.photo_album_id) %>

代码中的其他位置是否使用@photos

如果您想完全避免第二次通话,只需拨打all上的@photos方法即可。像这样:

<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).all %>

然后对于所有后续使用,它将不会再次击中DB。如果您还想避免photo_album的数据库匹配,那么您可以使用include

<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).include(:photo_albums).all %>