渴望加载生成较慢的查询
Posted
技术标签:
【中文标题】渴望加载生成较慢的查询【英文标题】:Eager loading generating slower queries 【发布时间】:2011-07-20 03:40:48 【问题描述】:我正在优化我的应用程序并注意到一些有趣的事情。我最初在我的控制器中有这个语句
@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"
这与分页有关吗?是两者的结合吗?
【问题讨论】:
我今天也遇到了这个问题。我正在对一个 habtm 关联进行包含,它最终生成了一个包含模型的每个唯一 ID 的查询。这是all that i found on the issue 如果您将此作为答案发布,您将获得我的赞誉积分 =P 我认为您的问题将通过以下 Malte 的解决方案得到解决 【参考方案1】:是的,该查询似乎是由分页插件生成的。此查询对于估计总页数是必要的。
但如果您知道记录的数量(之前通过简单的SELECT COUNT(*) FROM "votes"
),您可以使用:total_entries
选项将该数字传递给 will_paginate!
(有关详细信息,请参阅WillPaginate::Finder::ClassMethods。)
顺便说一句,您是否为votes.user_id
创建了索引?可能是减慢了查询速度。我想知道为什么 DISTINCT
子句会占用这么多时间,因为 id
可能已经有一个唯一的约束(如果没有,请尝试添加一个)。
【讨论】:
是的!这消除了那个 SQL 请求!谢谢!我只是使用了c = Vote.count
和@votes = Vote.includes(:user).paginate(:page => params[:page], :order=>"created_at DESC", :total_entries => c)
回答您的问题,是的,我在votes.user_id
上有一个索引。我认为查询花费这么长时间的原因是它正在执行外部连接?我仍然很困惑为什么我在使用includes
时会从 will_paginate 得到这个查询,但不是没有。以上是关于渴望加载生成较慢的查询的主要内容,如果未能解决你的问题,请参考以下文章