У меня есть запрос 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