Postgres:计算LEFT JOIN记录计数时的性能

时间:2019-06-13 01:32:32

标签: postgresql performance

我有一个工作于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

0 个答案:

没有答案