↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0
历史版本。 PostgreSQL 10 已结束支持。 2022-11-10. 请参阅 当前版本手册.

REINDEX

REINDEX — 重建索引

大纲

REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } name

描述

REINDEX 使用索引所属表中存储的数据重建索引,并替换索引的旧副本。以下几种场景适合使用 REINDEX:

  • 一个索引已经损坏,不再包含有效数据。尽管理论上这不该发生,但在实践中索引可能因软件缺陷或硬件故障而损坏。REINDEX 提供了一种恢复方法。

  • 一个索引已经“膨胀”,也就是说其中包含许多空页或几乎为空的页。在 PostgreSQL 中,B-树索引在某些不常见的访问模式下可能出现这种情况。REINDEX 可通过写入一个不含死页的新版本索引来减少索引的空间消耗。详见第 24.2 节。

  • 你修改了某个索引的存储参数(例如 fillfactor),并希望确保该更改已经完全生效。

  • 使用 CONCURRENTLY 选项构建索引失败后,会留下一个“无效”索引。这类索引没有用处,但用 REINDEX 重建它们可能很方便。注意,REINDEX 不会进行并发构建。要在不干扰生产运行的情况下构建索引,应删除该索引并重新执行 CREATE INDEX CONCURRENTLY 命令。

参数

INDEX

重新创建指定的索引。

TABLE

重新创建指定表的所有索引。如果该表有一个辅助“TOAST”表,也会对其重新索引。

SCHEMA

重新创建指定模式中的所有索引。如果该模式中的某个表有一个辅助“TOAST”表,也会对其重新索引。共享系统目录上的索引也会被处理。这种形式的 REINDEX 不能在事务块内执行。

DATABASE

重新创建当前数据库中的所有索引。共享系统目录上的索引也会被处理。这种形式的 REINDEX 不能在事务块内执行。

SYSTEM

重新创建当前数据库内系统目录上的所有索引。共享系统目录上的索引也包含在内。用户表上的索引不会被处理。这种形式的 REINDEX 不能在事务块内执行。

name

要重新索引的特定索引、表或数据库的名称。索引名和表名可以带模式限定。目前,REINDEX DATABASE 和 REINDEX SYSTEM 只能对当前数据库重新索引,所以其参数必须与当前数据库名匹配。

VERBOSE

在每个索引被重建时打印进度报告。

注解

如果怀疑某个用户表上的索引已经损坏,可以使用 REINDEX INDEX 或 REINDEX TABLE 直接重建该索引,或者重建该表上的所有索引。

如果需要从系统表上的索引损坏中恢复,情况就更复杂了。在这种情况下,重要的是系统本身没有使用任何可疑索引。(事实上,在这种场景下,你可能会发现服务器进程在启动时立即崩溃,因为它依赖损坏的索引。)要安全恢复,必须用 -P 选项启动服务器,该选项会阻止服务器在查找系统目录时使用索引。

一种做法是关闭服务器,并在命令行中包含 -P 选项来启动单用户 PostgreSQL 服务器。然后可以根据希望重建的范围,执行 REINDEX DATABASE、REINDEX SYSTEM、REINDEX TABLE 或 REINDEX INDEX。如果拿不准,就使用 REINDEX SYSTEM 来重建该数据库中的所有系统索引。然后退出单用户服务器会话并重新启动常规服务器。关于如何与单用户服务器接口交互的更多信息,参见 postgres 参考页。

另一种方法是启动一个常规服务器会话,并在其命令行选项中包含 -P。具体做法因客户端而异,但对于所有基于 libpq 的客户端,都可以在启动客户端之前将环境变量 PGOPTIONS 设置为 -P。注意,尽管这种方法不需要阻止其他客户端,但在修复完成之前,阻止其他用户连接到受损数据库可能仍然更稳妥。

REINDEX 类似于删除并重新创建索引,因为索引内容都是从头重建的。不过,两者在锁方面的考量相当不同。REINDEX 会阻止该索引所属表上的写入,但不阻止读取。它还会对正在处理的特定索引获取 ACCESS EXCLUSIVE 锁,从而阻塞试图使用该索引的读取。相比之下,DROP INDEX 会短暂地对父表获取 ACCESS EXCLUSIVE 锁,同时阻塞写入和读取。随后的 CREATE INDEX 会阻止写入但不阻止读取;由于索引不存在,读取不会尝试使用它,因此不会发生阻塞,但读取可能被迫使用代价高昂的顺序扫描。

对单个索引或表重新索引,要求用户是该索引或表的拥有者。对数据库重新索引,则要求用户是该数据库的拥有者(因此,拥有者可以重建其他用户所拥有表的索引)。当然,超级用户始终可以重新索引任何对象。

示例

重建单个索引:

REINDEX INDEX my_index;

重建表 my_table 上的所有索引:

REINDEX TABLE my_table;

在不假定系统索引已经有效的情况下,重建某个数据库中的所有索引:

$ export PGOPTIONS="-P"
$ psql broken_db
...
broken_db=> REINDEX DATABASE broken_db;
broken_db=> \q

兼容性

在 SQL 标准中没有 REINDEX 命令。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.