REINDEX — 重建索引
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 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 DATABASE、 REINDEX SCHEMA或REINDEX SYSTEM 时,除非该用户拥有共享系统目录(而这通常并非如此),否则会跳过共享 系统目录上的索引。当然,超级用户始终可以重新索引任何对象。
不支持对分区表或分区索引重新索引。可以改为分别对每个分区重新索引。
重建单个索引:
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命令。