我正在优化我的应用并注意到一些有趣的东西。我最初在我的控制器中有这个陈述
@votes = Vote.paginate(:page => params[:page], :order=>"created_at DESC")
这在我看来
<% @votes.each do |vote| %>
<tr>
<td><%= vote.user.display_name %></td>
...
我尝试更改控制器以使用预先加载:
@votes = Vote.includes(:user).paginate(:page => params[:page],
:order=>"created_at DESC")
这样做,我注意到我的ActiveRecord查询时间加载投票/索引从180毫秒加倍到440毫秒。通过急切加载成功减少了查询数量。但是,我在急切的负载情况仅:
中发现了这个耗时的查询 SQL (306.5ms) SELECT COUNT(DISTINCT "votes"."id") FROM "votes" LEFT OUTER JOIN "users" ON "users"."id" = "votes"."user_id"
为什么我的代码要求对左外连接进行计数?它不存在于非急切负载的情况下。在非急切负载的情况下,这是我能找到的最接近的陈述:
SQL (30.5ms) SELECT COUNT(*) FROM "votes"
这是与paginate有关吗?这是两者的某种组合吗?
答案 0 :(得分:2)
是的,该查询似乎是由分页插件生成的。此查询是估计总页数所必需的。
但是如果你知道记录的数量(通过之前做一个简单的SELECT COUNT(*) FROM "votes"
),你可以使用:total_entries
选项将该数字传递给will_paginate!
(有关详细信息,请参阅WillPaginate::Finder::ClassMethods。)
顺便问一下,您是否为votes.user_id
创建了一个索引?可能会减慢查询速度。我想知道为什么DISTINCT
子句应该花费这么多时间,因为id
可能已经有一个唯一约束(如果没有,请尝试添加一个)。