Postgres: производительность при подсчете количества записей LEFT JOIN - PullRequest
1 голос
/ 13 июня 2019

У меня есть запрос 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...