在 PostgreSQL 中检测 CREATE INDEX CONCURRENTLY 何时完成

Ama*_*rus 11 postgresql index concurrency

如果我在 PostgreSQL 中同时创建了一个索引,我如何才能看到它何时完成?

我正在尝试重建索引以解决索引膨胀问题,我需要将旧索引保留一段时间直到新索引完成,所以我需要知道它何时完成。

这是 PostgreSQL 9.2/3ish

Ane*_*pic 9

结合@Rory 的评论和@Zaytsev Dmitry 的回答中的信息:

CREATE INDEX CONCURRENTLY不会返回,直到该指数已完成建设。因此,当您的查询返回时,您知道索引已完成。

但是,如果您正在构建一个大型索引,您可能想知道它是否“真的”仍在运行。

您可以对“无效”索引使用查询:

SELECT * FROM pg_class, pg_index WHERE pg_index.indisvalid = false AND pg_index.indexrelid = pg_class.oid;
Run Code Online (Sandbox Code Playgroud)

...如果您的索引出现在结果中,那么它要么失败,要么仍在进行中

确认后者的另一种方法是检查锁表:

SELECT a.datname,
         l.relation::regclass,
         l.transactionid,
         l.mode,
         l.GRANTED,
         a.usename,
         a.query,
         a.query_start,
         age(now(), a.query_start) AS "age",
         a.pid
FROM pg_stat_activity a
JOIN pg_locks l ON l.pid = a.pid
WHERE mode = 'ShareUpdateExclusiveLock'
ORDER BY a.query_start;
Run Code Online (Sandbox Code Playgroud)

尽管 CONCURRENTLY 不会对表采取排他锁,但它会持有一个较弱的锁ShareUpdateExclusiveLock,您应该在此查询的结果中看到这一点。

如果没有锁定,则意味着索引已完成构建,或者创建失败并留下无效索引。

因此,在这两个查询之间,您可以确定索引处于三种可能状态(已完成/进行中/失败)中的哪一个。

  • 请注意,对于 Postgres 12,有一个系统视图显示创建索引的进度:https://www.postgresql.org/docs/current/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING (4认同)

Log*_*try 8

您可以获得无效索引的列表。

SELECT * FROM pg_class, pg_index WHERE pg_index.indisvalid = false AND pg_index.indexrelid = pg_class.oid;
Run Code Online (Sandbox Code Playgroud)

如果您在此查询中看到您的索引,则意味着该索引将不起作用,您必须重新创建索引。

不要做REINDEX。它不会并发地重新创建索引,它会在创建索引时锁定表以进行写入,最好的解决方案是删除无效索引并使用CONCURRENTLY标志重新创建它