【问题标题】:Postgres index-only scan taking too longPostgres 仅索引扫描耗时太长
【发布时间】:2019-08-28 23:52:33
【问题描述】:

我有一个具有以下结构和索引的表:

     Table "public.client_data"
         Column          |  Type   | Modifiers 
-------------------------+---------+-----------
 account_id              | text    | not_null
 client_id               | text    | not null
 client_type             | text    | not null
 creation_time           | bigint  | not null
 last_modified_time      | bigint  | not null

 Indexes:
    "client_data_pkey" PRIMARY KEY, btree (account_id, client_id)
    "client_data_last_modified_time_index" btree (last_modified_time)

我需要从这个表中找到最旧的记录 - 为此我使用了以下查询:

SELECT last_modified_time FROM client_data ORDER BY last_modified_time ASC LIMIT 1;

但是,在 AWS Aurora Postgres 9.6 中的 db.r4.2xlarge RDS 实例中,此表上大约 6100 万行的查询运行速度非常慢(90-100 分钟),没有其他并发查询在运行。

但是,将查询更改为使用 DESC 会立即完成。可能是什么问题呢?我期待,因为我有一个 last_modified_time 的索引,仅查询由该列排序并应用了限制的列将涉及一个仅索引查询,该查询应在索引中的第一个条目之后停止。

这里是解释分析的输出:

EXPLAIN ANALYZE SELECT last_modified_time FROM client_data ORDER BY last_modified_time ASC LIMIT 1;

                                                                                                   QUERY PLAN                                                                                                   
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.57..2.31 rows=1 width=8) (actual time=6297823.287..6297823.287 rows=1 loops=1)
   ->  Index Only Scan using client_data_last_modified_time_index on client_data  (cost=0.57..1049731749.38 rows=606590292 width=8) (actual time=6297823.287..6297823.287 rows=1 loops=1)
         Heap Fetches: 26575013
 Planning time: 0.078 ms
 Execution time: 6297823.306 ms

DESC 版本的查询结果相同

EXPLAIN ANALYZE SELECT last_modified_time FROM client_data ORDER BY last_modified_time DESC LIMIT 1;
                                                                                                 QUERY PLAN                                                                                                  
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.57..2.32 rows=1 width=8) (actual time=2.265..2.266 rows=1 loops=1)
   ->  Index Only Scan Backward using client_data_last_modified_time_index on client_data  (cost=0.57..1066049674.69 rows=611336085 width=8) (actual time=2.264..2.264 rows=1 loops=1)
         Heap Fetches: 9
 Planning time: 0.095 ms
 Execution time: 2.278 ms

任何指针?

【问题讨论】:

  • 看起来 postgres 经常访问堆,可能是为了检查旧行的可见性。 autovacuum 是否跟上此表中的更改?
  • 不确定,但自动吸尘器最近运行过,可能是这样。
  • 是否有可能有很多 first 相同的 last_modified_time(与 ASC),但只有少数 last last_modified_time(与 @987654329 @)?

标签: database postgresql query-optimization rdbms


【解决方案1】:

区别是这样的:

缓慢的计划有

Heap Fetches: 26575013

快速计划

Heap Fetches: 9

堆提取是将快速的仅索引扫描转变为慢速的普通索引扫描。

该表最近是否经历过大规模更新或删除?

缓慢扫描的原因是它必须在第一次匹配之前遍历许多不可见(已删除)的元组。

在桌子上运行VACUUM,两次扫描都会很快。

【讨论】:

  • 我们确实对表进行了删除操作,删除了超过 30 天的数据。删除完成后,我们运行最旧的记录查询以进行监控。运行最旧记录查询时,删除已完成,直到最旧记录查询完成后才会运行。此外,ASC 和 DESC 查询可互换运行多次,每次 DESC 查询完成但 ASC 查询卡住。
  • 我的错,我没有注意到LIMIT。我已经更新了答案。
  • 谢谢。我会试试的。您之前的文章链接提供了非常丰富的信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 1970-01-01
相关资源
最近更新 更多