2012-08-09 240 views
3

我不知道为什么这样做为什么此查询运行缓慢?

UserView.where(:user_viewable_type => 'Song').order('created_at desc').limit(5) 

需要1213ms运行。有点慢吗?

在schema.rb user_viewable_type被索引:

add_index "user_views", ["user_viewable_type"], :name => "index_views_on_viewable_type" 

即使在PSQL:

"index_views_on_viewable_type" btree (user_viewable_type) 

.explain回报运行:

UserView.where(:user_viewable_type => 'Song').order('created_at desc').limit(5).explain 
    UserView Load (1801.4ms) SELECT "user_views".* FROM "user_views" WHERE "user_views"."user_viewable_type" = 'Song' ORDER BY created_at desc LIMIT 5 
    EXPLAIN (1.6ms) EXPLAIN SELECT "user_views".* FROM "user_views" WHERE "user_views"."user_viewable_type" = 'Song' ORDER BY created_at desc LIMIT 5 
=> "EXPLAIN for: SELECT \"user_views\".* FROM \"user_views\" WHERE \"user_views\".\"user_viewable_type\" = 'Song' ORDER BY created_at desc LIMIT 5\n         QUERY PLAN\n-------------------------------------------------------------------------------\n Limit (cost=17113.28..17113.28 rows=5 width=37)\n -> Sort (cost=17113.28..17147.82 rows=69085 width=37)\n   Sort Key: created_at\n   -> Seq Scan on user_views (cost=0.00..16883.78 rows=69085 width=37)\n    Filter: ((user_viewable_type)::text = 'Song'::text)\n(5 rows)\n" 

所以我决定打破查询下来并删除order,我得到:

UserView.where(:user_viewable_type => 'Song').limit(5).explain 
UserView Load (1.6ms) SELECT "user_views".* FROM "user_views" WHERE "user_views"."user_viewable_type" = 'Song' LIMIT 5 

看起来order('created_at desc')导致查询变慢。但为什么?难道不能很快下单吗?

我试图在该idorder

UserView.where(:user_viewable_type => 'Song').order('id desc').limit(5).explain 
UserView Load (44.8ms) SELECT "user_views".* FROM "user_views" WHERE "user_views"."user_viewable_type" = 'Song' ORDER BY id desc LIMIT 5 

如此之快!什么可能是错的?

几件事我应该提到:

  1. 如果你还没有注意到,这是一个多态表。
  2. 过去,我通过经由t.rename :live_viewable_type, :user_viewable_type的Rails迁移,将:live_viewable_type更名为:user_viewable_type。但是,我认为这不应该成为问题,因为索引仍然在右栏。
+0

将问题中的“解释”替换为“解释分析”,并用换行符将其格式化为代码,以便可读。 – 2012-08-09 17:49:23

回答

3

的问题,据我所知,可能是两种:

一)你是不是在created_at

或索引:

二)数据库选择一个索引或另一个索引(即使用created_at索引,使user_viewable_type规范变慢,反之亦然)。

如果您经常拨打这些电话,可能需要查看[created_at, user_viewable_type](或其他方式:[user_viewable_type, created_at],取决于哪种方法可以更快地缩小您的结果)的组合索引。

+0

我刚刚阅读的一篇类似文章解释了你的建议:http://tomafro.net/2009/08/using-indexes-in-rails-choosing-additional-indexes – 2012-08-09 17:51:40

+0

对,他写的很顺利我在想什么。如果你对'[created_at,user_viewable_type]'做了索引,你的结果会更好吗? – DRobinson 2012-08-09 17:56:52

+0

是的,绝对更好! – 2012-08-09 19:17:34