通过Postgres/rails解释数据了解如何优化查询

3
我有以下查询:
c = Invite.where(:invite_method => 'email', :email => email, :created_at => Time.zone.now.beginning_of_day..Time.zone.now.end_of_day).count

这个查询需要一些时间,因为表格中有超过一百万条记录。以下是查询结果:

> invites_sent_today = Invite.where(:invite_method => 'email', :email => email, :created_at => Time.zone.now.beginning_of_day..Time.zone.now.end_of_day).exp 

Invite Load (62.3ms)  SELECT "invites".* FROM "invites" WHERE "invites"."invite_method" = 'email' AND "invites"."email" = 'santa@site.com' AND ("invites"."created_at" BETWEEN '2013-01-20 00:00:00.000000' AND '2013-01-20 23:59:59.999999')

EXPLAIN (2.2ms)  EXPLAIN SELECT "invites".* FROM "invites" WHERE "invites"."invite_method" = 'email' AND "invites"."email" = 'santa@site.com' AND ("invites"."created_at" BETWEEN '2013-01-20 00:00:00.000000' AND '2013-01-20 23:59:59.999999')

=> EXPLAIN for:

SELECT \"invites\".*
  FROM \"invites\"
 WHERE \"invites\".\"invite_method\" = 'email' 
   AND \"invites\".\"email\" = 'santa@site.com'
   AND (\"invites\".\"created_at\"
    BETWEEN '2013-01-2000:00:00.000000'                                                             
       AND'2013-01-20 23:59:59.999999'
      ;

QUERY PLAN\n------------------------------------------------------------------------------------------------------------------------------------------------------------------\n 
Index Scan using index_invites_on_created_at on invites  (cost=0.00..17998.11 rows=2 width=129)\n   
Index Cond: ((created_at >= '2013-01-20 00:00:00'::timestamp without time zone) AND (created_at <= '2013-01-20 23:59:59.999999'::timestamp without time zone))\n   
Filter: (((invite_method)::text = 'email'::text) AND ((email)::text = 'santa@site.com'::text))\n(3 rows)\n"

有什么建议可以提高这个查询的性能吗?谢谢。


1
复合或部分索引可以加快此特定查询的速度。 - Ihor Romanchenko
1
例子:CREATE INDEX zzzzz ON invites (email) WHERE invite_method = 'email' 顺便说一句:检查查询计划的方法是运行 EXPLAIN ANALYZE query statement,并观察观察结果和预期之间的差异。 - wildplasser
2
你是否总是查询最近 24 小时的数据?如果是 -> 创建额外的表并在每天结束时进行截断,这样查询速度会更快。如果电子邮件的基数更好,则在电子邮件上创建索引。 - baklarz2048
1
@iddqd 或许最近一天的部分索引会更好?并在一天结束时重新创建索引。 - Ihor Romanchenko
2
@AnApprentice 如果你想要一个针对最近一天(或三天等)数据的部分索引,你必须重新创建索引,因为“最近一天”不断变化。如果你想要一个针对像“invite_method”=‘email’这样的部分索引,你就不需要重新创建它。 - Ihor Romanchenko
显示剩余7条评论
1个回答

0

正如Igor所建议的那样,尝试使用复合索引:

CREATE INDEX index_invites_email_created_at on invites(email,created_at);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接