选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

REINDEX

REINDEX — 重建索引

Synopsis

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

描述

REINDEX利用索引所属表中存储的数据重建索引,替换该索引的旧副本。以下几种情况适合使用REINDEX

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

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

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

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

参数

INDEX

重新创建指定的索引。

TABLE

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

SCHEMA

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

DATABASE

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

SYSTEM

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

name

要重新索引的特定索引、表或数据库的名称。索引名和表名可以带模式限 定。目前,REINDEX DATABASEREINDEX SYSTEM只能对当前数据库重新索引。它们的参 数是可选的,但如果给出,就必须与当前数据库名匹配。

VERBOSE

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

注解

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

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

一种做法是关闭服务器,并在命令行中包含-P选项来启 动单用户 PostgreSQL 服务器。然后可以根据 希望重建的范围,执行REINDEX DATABASEREINDEX SYSTEMREINDEX TABLEREINDEX 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命令。