我继承了性能特别慢的查询,但我不清楚维护功能和降低查询成本的最佳途径。
查询的简化版本如下:
select * from api_event where COALESCE(
(SELECT count(*) FROM api_ticket WHERE
event_id = api_event.id),
0
) < api_event.ticket_max AND COALESCE(
(SELECT count(*) FROM api_ticket WHERE
api_ticket.user_id = 45187 AND event_id = api_event.id
and api_ticket.status != 'x'),
0
) < api_event.ticket_max_per_user;
运行Explain / Analyze就好像告诉我这需要在api_event表上进行顺序扫描:
Seq Scan on api_event (cost=0.00..69597.99 rows=448 width=243) (actual time=0.059..230.981 rows=1351 loops=1)
Filter: ((COALESCE((SubPlan 1), 0::bigint) < ticket_max) AND (COALESCE((SubPlan 2), 0::bigint) < ticket_max_per_user))
Rows Removed by Filter: 2647
关于如何改善这一点的任何建议?
答案 0 :(得分:0)
将查询重写为显式join
可能会有所帮助:
select e.*
from api_event e left join
(select t.event_id, count(*) as cnt,
sum(case when t.user_id = 45187 and t.status <> 'x' then 1 else 0
end) as special_cnt
from api_ticket t
group by t.event_id
) t
on e.id = t.event_id
where coalesce(t.cnt, 0) < e.ticket_max and
coalesce(special_cnt, 0) < e.ticket_max_per_user;
答案 1 :(得分:0)
这是一个腐蚀的子查询,最近我通过使用基于with
的查询避免了腐蚀的子查询来提高了一些查询的性能,它在Oracle中非常快,我希望它可以帮助你使用Postgres。