我有一个工作于Postgres的查询,但执行速度比预期的慢。
SELECT
"post"."id",
COUNT(DISTINCT l.id) AS num_likes,
COUNT(DISTINCT ul.id) AS num_user_likes,
COUNT(DISTINCT c.id) AS num_comments
FROM "post"
LEFT JOIN "like" AS "l" ON "l"."post_id" = "post"."id"
LEFT JOIN "like" AS "ul" ON "ul"."post_id" = "post"."id" AND "ul"."user_id" = 1
LEFT JOIN "comment" AS "c" ON "c"."post_id" = "post"."id"
GROUP BY "post"."id"
如果省略LEFT JOIN
语句之一,查询速度将很快,但是一旦添加第三个语句,查询速度将降低5-10倍。根据对连接的基本了解,Postgres是否应该将这些表分别连接到post
?为什么在第三次加入后出现峰值?
我该如何重写该查询以提高性能?
在本地查询上运行EXPLAIN (ANALYZE, BUFFERS)
会产生以下结果:
GroupAggregate (cost=26.31..114.09 rows=12 width=28) (actual time=11.466..11.580 rows=15 loops=1)
Group Key: post.id
Buffers: shared hit=13
-> Merge Left Join (cost=26.31..80.52 rows=3345 width=16) (actual time=0.171..6.298 rows=20443 loops=1)
Merge Cond: (post.id = l.post_id)
Buffers: shared hit=13
-> Merge Left Join (cost=8.49..11.98 rows=217 width=12) (actual time=0.085..0.682 rows=2042 loops=1)
Merge Cond: (post.id = ul.post_id)
Buffers: shared hit=4
-> Sort (cost=5.40..5.53 rows=51 width=8) (actual time=0.061..0.067 rows=60 loops=1)
Sort Key: post.id
Sort Method: quicksort Memory: 27kB
Buffers: shared hit=3
-> Hash Right Join (cost=2.27..3.96 rows=51 width=8) (actual time=0.027..0.048 rows=60 loops=1)
Hash Cond: (l.post_id = post.id)
Buffers: shared hit=3
-> Seq Scan on like l (cost=0.00..1.51 rows=51 width=8) (actual time=0.005..0.009 rows=49 loops=1)
Buffers: shared hit=1
-> Hash (cost=2.12..2.12 rows=12 width=4) (actual time=0.017..0.017 rows=15 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 9kB
Buffers: shared hit=2
-> Seq Scan on post (cost=0.00..2.12 rows=12 width=4) (actual time=0.009..0.012 rows=15 loops=1)
Buffers: shared hit=2
-> Sort (cost=3.08..3.21 rows=51 width=8) (actual time=0.021..0.212 rows=2030 loops=1)
Sort Key: ul.post_id
Sort Method: quicksort Memory: 27kB
Buffers: shared hit=1
-> Seq Scan on like ul (cost=0.00..1.64 rows=51 width=8) (actual time=0.004..0.012 rows=49 loops=1)
Filter: (user_id = 1)
Buffers: shared hit=1
-> Sort (cost=17.82..18.28 rows=185 width=8) (actual time=0.084..1.506 rows=20438 loops=1)
Sort Key: c.post_id
Sort Method: quicksort Memory: 34kB
Buffers: shared hit=9
-> Seq Scan on comment c (cost=0.00..10.85 rows=185 width=8) (actual time=0.004..0.045 rows=192 loops=1)
Buffers: shared hit=9
Planning Time: 0.319 ms
Execution Time: 11.624 ms