0

我的操作填充了一个实例变量@websites- 它从数据库中获取。

@websites = Website.all

我可以浏览一下@websites,看到只有一个对数据库的调用。快乐的时光。

<% @websites.each do |website| %>
...
<% end %>

这导致:

Website Load (0.1ms) SELECT "websites".* FROM "websites"   

但如果我用这样的包装它present?

<% if @websites.present? %>
   <% @websites.each do |website| %>
   <% end %>
<% else %>

现在我得到两个数据库调用

(0.2ms)  SELECT COUNT(*) FROM "websites"
Website Load (0.1ms) SELECT "websites".* FROM "websites" 

为什么要进行两次数据库调用?以及如何停止拨打第二个电话。

对我来说,该@websites变量将所有网站都保存在内存中。当然,rails 只会计算内存中的项目,而不是在数据库上执行新的 SELECT 吗?

4

1 回答 1

1

这个方法调用,

@websites = 网站.all

不会立即将记录加载到内存中。它只是一个活动的记录关系。对这个关系执行的第一个操作是调用present?and 来满足这个请求,Rails 不需要将所有记录加载到内存中。所以 ActiveRelation 只是优化关系并进行计数查询以获得结果。现在只有当您@websites使用 each 方法访问时才会加载记录。

如果你想避免那个额外的查询,你可以将 Relation 转换为一个数组,但是这样做,

@websites = Website.all.to_a

这会加载记录并呈现一个Array而不是ActiveRelation. 但问题是活动关系不能用这种关系链接进一步的查询。但我假设在你的情况下这不是必需的。

于 2012-11-18T18:32:41.710 回答