【问题标题】:Explain analyze slower than actual query in postgres解释分析比 postgres 中的实际查询慢
【发布时间】:2021-06-11 00:26:30
【问题描述】:

我有以下问题

select * from activity_feed where user_id in (select following_id from user_follow where follower_id=:user_id)
union 
select * from activity_feed where project_id in (select project_id from user_project_follow where user_id=:user_id)
order by id desc limit 30

根据 postico 大约需要 14 毫秒

但是当我在此查询上执行explain analyze 时,计划时间为 0.5 毫秒,执行时间约为 800 毫秒(这是我实际期望的)。这是因为没有explain analyze 的查询正在返回缓存结果吗?即使在这种情况下,我仍然得到不到 20 毫秒的结果。使用其他值。

哪一个更能说明我将在生产中获得的性能?我还意识到这是一个相当低效的查询,我似乎无法找出一个可以提高效率的索引。我可能不得不不使用union

编辑:执行计划

Limit  (cost=1380.94..1380.96 rows=10 width=148) (actual time=771.111..771.405 rows=10 loops=1)
  ->  Sort  (cost=1380.94..1385.64 rows=1881 width=148) (actual time=771.097..771.160 rows=10 loops=1)
        Sort Key: activity_feed."timestamp" DESC
        Sort Method: top-N heapsort  Memory: 27kB
        ->  HashAggregate  (cost=1321.48..1340.29 rows=1881 width=148) (actual time=714.888..743.273 rows=4462 loops=1)
              Group Key: activity_feed.id, activity_feed."timestamp", activity_feed.user_id, activity_feed.verb, activity_feed.object_type, activity_feed.object_id, activity_feed.project_id, activity_feed.privacy_level, activity_feed.local_time, activity_feed.local_date
              ->  Append  (cost=5.12..1274.46 rows=1881 width=148) (actual time=0.998..682.466 rows=4487 loops=1)
                    ->  Hash Join  (cost=5.12..610.43 rows=1350 width=70) (actual time=0.982..326.089 rows=3013 loops=1)
                          Hash Cond: (activity_feed.user_id = user_follow.following_id)
                          ->  Seq Scan on activity_feed  (cost=0.00..541.15 rows=24215 width=70) (actual time=0.016..150.535 rows=24215 loops=1)
                          ->  Hash  (cost=4.78..4.78 rows=28 width=8) (actual time=0.911..0.922 rows=29 loops=1)
                                Buckets: 1024  Batches: 1  Memory Usage: 10kB
                                ->  Index Only Scan using unique_user_follow_pair on user_follow  (cost=0.29..4.78 rows=28 width=8) (actual time=0.022..0.334 rows=29 loops=1)
                                      Index Cond: (follower_id = '17420532762804570'::bigint)
                                      Heap Fetches: 0
                    ->  Hash Join  (cost=30.50..635.81 rows=531 width=70) (actual time=0.351..301.945 rows=1474 loops=1)
                          Hash Cond: (activity_feed_1.project_id = user_project_follow.project_id)
                          ->  Seq Scan on activity_feed activity_feed_1  (cost=0.00..541.15 rows=24215 width=70) (actual time=0.027..143.896 rows=24215 loops=1)
                          ->  Hash  (cost=30.36..30.36 rows=11 width=8) (actual time=0.171..0.182 rows=11 loops=1)
                                Buckets: 1024  Batches: 1  Memory Usage: 9kB
                                ->  Index Only Scan using idx_user_project_follow_temp on user_project_follow  (cost=0.28..30.36 rows=11 width=8) (actual time=0.020..0.102 rows=11 loops=1)
                                      Index Cond: (user_id = '17420532762804570'::bigint)
                                      Heap Fetches: 11
Planning Time: 0.571 ms
Execution Time: 771.774 ms

提前感谢您的帮助!

【问题讨论】:

  • 不太可能产生如此大的差异,但EXPLAIN (ANALYZE) 完成的所有时钟调用都会减慢它的速度。如果你这样做 EXPLAIN (ANALYZE, TIMING OFF) 会发生什么?
  • 请出示计划。
  • 也许 psql 和 postico 使用了不同的设置,这使得计划不同(比如 postico 可能将其隐式包装在游标中)。能否让 postico 本身向您展示执行计划?
  • @jjanes 将计划添加到问题中。另外,您说得对,EXPLAIN (ANALYZE, TIMING OFF) 实际上确实将其降低到了 9 毫秒。我认为如果桌子变大,最终union 将证明效率太低,但这是另一天的担忧

标签: sql postgresql indexing query-optimization sql-execution-plan


【解决方案1】:

像您在此处显示的那样非常慢的时钟访问(当 TIMING 默认为 ON 时慢近 100 倍!)通常表示旧硬件或旧内核 IME。如果您非常注重性能,则无法信任 EXPLAIN (ANALYZE) 来获得良好的数据可能会非常令人沮丧,因此您应该考虑升级您的硬件或操作系统。

【讨论】:

  • 谢谢!使用 docker 镜像进行本地测试 postgres:11.1-alpine。我想如果我使用托管 RDS,那么在 prod 上这不会是一个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 2015-05-23
  • 2017-04-30
  • 2015-01-28
  • 2012-07-23
  • 1970-01-01
  • 2012-08-26
相关资源
最近更新 更多