REINDEX

Name

REINDEX -- 重建索引

Synopsis

REINDEX { INDEX | TABLE | DATABASE | SYSTEM } name [ FORCE ]

描述

REINDEX 使用存储在索引的表上的数据重建索引, 替换旧的索引拷贝。使用 REINDEX 有两个主要原因:

参数

INDEX

重新建立声明了的索引。

TABLE

重新建立声明的表的所有索引。如果表有个从属的"TOAST"表,那么这个表也会重新索引。

DATABASE

重建当前数据库里的所有索引。 除非在独立运行模式下,会忽略在共享系统表上的索引(见下文)。

SYSTEM

在当前数据库上重建所有系统表上的索引。不会处理在用户表上的索引。 另外,除了是在单主机模式下,共享的系统表也会被忽略(见下文)。

name

需要重建索引的索引,表或者数据库的名称。 表和索引名可以有模式修饰。 目前,REINDEX DATABASEREINDEX SYSTEM 只能重建当前数据库的索引, 因此其参数必须匹配当前数据库的名字。

FORCE

这是一个废弃的选项,如果声明,会被忽略。

注意

如果你怀疑一个用户表上的索引崩溃了,你可以简单地重建该索引, 或者该表上地所有索引,使用 REINDEX INDEX 或者 REINDEX TABLE

如果你从一个崩溃的系统表索引上恢复,事情会更棘手一些。 这种情况下,系统必须不能使用任何有疑问的索引。 (实际上,在这种情况下,你可能发现服务器进程在启动之后马上就崩溃了, 因为依赖于崩溃了的索引。)要想安全恢复,服务器必须带着 -P 选项启动, 它禁止服务器在查找系统表的时候使用索引。

这么做个一个办法事停止 postmaster 然后带着 -P 命令行选项启动一个独立的 PostgreSQL 服务器。 然后,根据你希望恢复的程度,可以发出 REINDEX DATABASEREINDEX SYSTEMREINDEX TABLE,或者 REINDEX INDEX。 如果还有怀疑,使用 REINDEX SYSTEM 选择重新构造数据库中全部的系统索引。 然后退出独立服务器会话并且重启普通的服务器。 参阅 postgres 手册页获取有关如何与独立服务器交互的信息。

另外,一个普通的会话可以在其命令行选项里带着 -P 启动。 这么做的方法因不同的客户端而异,但是在所有基于 libpq 的客户端上, 我们都可以通过在启动客户端之前设置 PGOPTIONS 环境变量为 -P 来实现。 请注意尽管这个方法并不要求锁住其它客户端,但是禁止其它客户端连接受损的数据库, 直到完成修补应该事一个明智的选择。

如果怀疑任何共享的系统表的索引损坏((pg_databasepg_grouppg_shadow 或者 pg_tablespace), 那么必须用独立服务器的方式来修复它。REINDEX 不能在多用户环境下处理共享系统表。

除了共享系统表之外的所有索引,REINDEX 是抗崩溃并且是事务安全的。 REINDEX 对于共享的索引而言不是抗崩溃的,这就是为什么不允许在正常操作中这么使用的原因。 如果在重新对一个共享表进行索引的时候发生了崩溃,那么在纠正问题之前,就不可能重新启动普通的服务器。 (一个建立了一部分的共享索引的典型症状是"index is not a btree/索引不是 btree 索引"错误。)

REINDEX 类似与删除再重建索引,表现在它们都是从零开始重建。 不过,从锁的角度考虑,两者是有区别的。REINDEX 锁住对索引的父表的写操作, 但是不会锁主读操作。并且它还在被处理的特定索引上保持一个排他锁, 这样它将阻止试图使用该索引的读操作。相比之下,DROP INDEX 在父表上短暂的保持一个排他锁,锁住读和写操作。随后的 CREATE INDEX 锁住写操作但是不会锁住读操作;因为索引还不存在,所以不会有试图使用它的读操作, 意味着操作中不会有阻塞,只不过读操作会被迫只能使用顺序扫描。 另外一个重要的环节是删除/重建的方法让所有使用索引的缓冲的查询规划都失效, 而 REINDEX 不会。

对一个索引或者表进行重建索引要求你是该索引或者表的所有这。 对一个数据库重建索引要求你是该数据库的所有者(请注意,这样这个所有者就可以重建其它用户拥有的索引)。 当然,超级用户总是可以重建所有东西的索引。

PostgreSQL 8.1 之前,REINDEX DATABASE 只处理系统索引,而不是人们从名字猜测的那样,处理所有索引。这个行为现在已经改变了,以减少意外的因素。 旧的行为可以通过 REINDEX SYSTEM 获得。

PostgreSQL 7.4 之前,REINDEX TABLE 并不自动处理 TOAST 表,因此这些表必须用独立的命令进行处理。这么做仍然可以,但是已经多余了。

例子

重建表 mytable 上的索引:

REINDEX TABLE mytable;

重建单个索引:

REINDEX INDEX my_index;

重建一个数据库上的所有系统索引,不管系统索引是否已经有效:

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

兼容性

SQL92里没有 REINDEX