如何在 PostgreSQL 上查找数据库重建索引的进度?

Cer*_*rin 5 postgresql index

运行时:

REINDEX DATABASE CONCURRENTLY mydb;
Run Code Online (Sandbox Code Playgroud)

这可能需要几个小时,甚至几天,具体取决于数据库的大小,是否有办法粗略估计其进度?

我看到一些论坛帖子声称您可以使用如下查询来查询索引创建状态:

SELECT 
  now()::TIME(0), 
  a.query, 
  p.phase, 
  p.blocks_total, 
  p.blocks_done, 
  p.tuples_total, 
  p.tuples_done,
FROM pg_stat_progress_create_index p 
JOIN pg_stat_activity a ON p.pid = a.pid;
Run Code Online (Sandbox Code Playgroud)

_done / _total 列与阶段相结合确实提供了粗略的进度百分比。但是,这仅列出当前更新索引的进度。它不会告诉您有多少其他索引正在等待更新,更不用说每个索引需要做多少工作了。

编辑:我尝试将 views 结合起来pg_index,其中列出了*_ccnew并发进程使用的临时索引,例如pg_stat_progress_create_index

SELECT relname,
CASE WHEN blocks_total > 0 THEN (ci.blocks_done/ci.blocks_total::numeric*100)::int ELSE NULL END as blocks_percent,
i.*
FROM pg_class as pgc
inner join pg_index as i on i.indexrelid = pgc.oid
left outer join pg_stat_progress_create_index as ci on ci.index_relid = i.indexrelid
WHERE i.indisvalid = false;
Run Code Online (Sandbox Code Playgroud)

但这显示了奇怪的结果。对于我的数据库,它在 pg_index 中列出了大约 300 个临时索引,等待更新。然而,pg_stat_progress_create_index 交叉引用的一个从未更新的索引被标记为有效。它处理了 100% 的块,然后消失,pg_stat_progress_create_index但它indisvalid仍然是错误的。为什么是这样?

Erw*_*ter 1

Postgres 12 或更高版本具有系统视图pg_stat_progress_create_index
据报道...

每个正在运行的后端占一行CREATE INDEXREINDEX,显示当前进度。

详细信息请参见手册的CREATE INDEX 进度报告一章。

这在繁忙的服务器上可能非常昂贵!

REINDEX DATABASE CONCURRENTLY mydb;
Run Code Online (Sandbox Code Playgroud)

该手册有一章CREATE INDEX Phases描述了列的状态phase。特别要考虑:

waiting for old snapshots

CREATE INDEX CONCURRENTLY或者REINDEX CONCURRENTLY正在等待可能看到该表的事务来释放其快照。当不处于并发模式时,将跳过此阶段。列lockers_totallockers_donecurrent_locker_pid包含此阶段的进度信息。

长时间运行的事务可能会阻碍进度。考虑REINDEX CONCURRENTLY在选定的索引上运行。在REINDEX DATABASE非工作时间,您可以专门锁定桌子。

如果您的服务器实际上并不繁忙,请使用以下命令检查长时间运行的事务:

SELECT * FROM pg_stat_activity;
Run Code Online (Sandbox Code Playgroud)

那些state = 'idle in transaction'是主要的麻烦制造者(通常暗示编程错误,其中事务未提交或回滚)。这些可能会出现在pg_stat_progress_create_index.current_locker_pid停滞的指数中。
有关的: