Postgresql 帮助改进查询。尝试使用解释

Postgresql 帮助改进查询。尝试使用解释,postgresql,optimization,sql-execution-plan,query-performance,Postgresql,Optimization,Sql Execution Plan,Query Performance,我有一个问题其实没那么复杂。跑步需要将近250毫秒,速度相当慢。我已经使用EXPLAIN分析了查询,并注意到一个seq扫描。我为该查询中使用的所有列准备了适当的索引。所以我不知道接下来该怎么办 以下是我所拥有的: cl_production=# EXPLAIN SELECT count(DISTINCT events.id) AS count_distinct_events_id FROM "events" INNER JOIN "events_tickets" ON "events_ticke

我有一个问题其实没那么复杂。跑步需要将近250毫秒,速度相当慢。我已经使用EXPLAIN分析了查询,并注意到一个seq扫描。我为该查询中使用的所有列准备了适当的索引。所以我不知道接下来该怎么办

以下是我所拥有的:

cl_production=# EXPLAIN SELECT count(DISTINCT events.id) AS count_distinct_events_id FROM "events" INNER JOIN "events_tickets" ON "events_tickets".event_id = "events".id INNER JOIN "tickets" ON "tickets".id = "events_tickets".ticket_id WHERE ((events.occurs_at > '2011-08-20 07:00:00.000000') AND (tickets.company_id = 175));
                                                       QUERY PLAN                                                       
------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=15735.79..15735.80 rows=1 width=4)
   ->  Hash Join  (cost=10540.01..15651.89 rows=33562 width=4)
         Hash Cond: (events_tickets.event_id = events.id)
         ->  Hash Join  (cost=3510.07..7516.61 rows=33562 width=4)
               Hash Cond: (events_tickets.ticket_id = tickets.id)
               ->  Seq Scan on events_tickets  (cost=0.00..1803.80 rows=124980 width=8)
               ->  Hash  (cost=3058.63..3058.63 rows=27475 width=4)
                     ->  Bitmap Heap Scan on tickets  (cost=521.19..3058.63 rows=27475 width=4)
                           Recheck Cond: (company_id = 175)
                           ->  Bitmap Index Scan on index_tickets_on_company_id  (cost=0.00..514.33 rows=27475 width=0)
                                 Index Cond: (company_id = 175)
         ->  Hash  (cost=5963.87..5963.87 rows=64965 width=4)
               ->  Index Scan using index_events_on_occurs_at on events  (cost=0.00..5963.87 rows=64965 width=4)
                     Index Cond: (occurs_at > '2011-08-20 07:00:00'::timestamp without time zone)
如上所述,以下是我从模式文件中获得的索引:

add_index "events_tickets", ["event_id", "ticket_id"], :name => "index_events_tickets_on_event_id_and_ticket_id", :unique => true
add_index "events_tickets", ["event_id"], :name => "index_events_tickets_on_event_id"
add_index "events_tickets", ["ticket_id"], :name => "index_events_tickets_on_ticket_id"
add_index "events", ["occurs_at"], :name => "index_events_on_occurs_at"
add_index "tickets", ["company_id"], :name => "index_tickets_on_company_id"
我假设序列扫描是终止这个查询的原因。我在那张表上有非常全面的索引。所以我迷路了。任何帮助都将不胜感激


谢谢。

您应该进行解释分析,以获得计划中每个节点的实际时间,而不仅仅是成本估算

这种使用半连接而不是计数不同聚合的查询形式可能有助于:

SELECT COUNT(*)
FROM events
WHERE EXISTS (SELECT 1
              FROM events_tickets
                   JOIN tickets ON tickets.id = events_tickets.ticket_id
              WHERE tickets.company_id = 175
                    AND events_tickets.event_id = events.id)
      AND events.occurs_at > '2011-08-20 07:00:00'::timestamp

您应该进行解释分析,以获得计划中每个节点的实际时间,而不仅仅是成本估算

这种使用半连接而不是计数不同聚合的查询形式可能有助于:

SELECT COUNT(*)
FROM events
WHERE EXISTS (SELECT 1
              FROM events_tickets
                   JOIN tickets ON tickets.id = events_tickets.ticket_id
              WHERE tickets.company_id = 175
                    AND events_tickets.event_id = events.id)
      AND events.occurs_at > '2011-08-20 07:00:00'::timestamp

你已经有多长时间没有做过完整的分析了?你有没有试过在表上运行一个
analyze
?你把id作为主键,并且定义了指向它们的外键,对吗?(如果这是非常明显的话,很抱歉)@andrew:这看起来像Rails的东西,任何地方都不会有真正的FK,所有的PK都会在
id serial
列上。@andrew没有,我有索引,但没有外键约束。这并不是说我不想要它们,但是Rails处理将多个模型保存到数据库的方式使得这不可能。但是从性能的角度来看,没有区别,对吗?索引就是索引。外键约束只是在关系上添加了一个有效性检查。您使用完整分析进行真空有多长时间了?您是否尝试在表上运行
analyze
?您将id作为主键,并定义了指向它们的外键,对吗?(如果这是非常明显的话,很抱歉)@andrew:这看起来像Rails的东西,任何地方都不会有真正的FK,所有的PK都会在
id serial
列上。@andrew没有,我有索引,但没有外键约束。这并不是说我不想要它们,但是Rails处理将多个模型保存到数据库的方式使得这不可能。但是从性能的角度来看,没有区别,对吗?索引就是索引。外键约束只是在关系上添加了一个有效性检查。谢谢,我很快意识到没有什么灵丹妙药可以提高查询的性能。不幸的是,对于我的ORM来说,这个解决方案是一个挑战,但它确实表现得更好。谢谢,我很快意识到,没有什么灵丹妙药可以提高查询的性能。不幸的是,对于我的ORM来说,这个解决方案是一个挑战,但它确实表现得更好。