REINDEX使用存储在索引表中的数据重建索引,替换旧的索引的副本。 使用REINDEX有两个主要原因:
索引崩溃,并且不再包含有效的数据。尽管理论上这是不可能发生的, 但实际上索引会因为软件毛病或者硬件问题而崩溃。REINDEX提供了一个恢复方法。
索引变得"臃肿",包含大量的空页或接近空页。 这个问题在某些罕见访问模式时会发生在 B-tree 索引上。REINDEX 通过写一个不带无用索引页的新索引提供了缩小索引空间消耗的途径。 参阅第 23.2 节获取更多信息。
为索引更改了存储参数(例如填充因子),并且希望这个更改完全生效。
使用CONCURRENTLY选项创建索引失败,留下了一个"非法"索引。 这样的索引毫无用处,但是可以通过REINDEX重建新索引来覆盖。注意, REINDEX不能并发创建。要在生产环境中重建索引并且尽可能减小对尖峰负载的影响, 可以先删除旧索引,然后使用CREATE INDEX CONCURRENTLY命令重建新索引。
重新建立指定的索引。
重新建立指定表的所有索引。如果表有从属的"TOAST"表,那么这个表也会重新索引。
重建当前数据库里的所有索引。也处理在共享系统表上的索引。 这种形式的REINDEX不能在事务块中执行。
在当前数据库上重建所有系统表上的索引。包括在共享系统表上的索引。不会处理在用户表上的索引。 这种形式的REINDEX不能在事务块中执行。
需要重建索引的索引、表、数据库的名称。表和索引名可以有模式修饰。目前, REINDEX DATABASE和REINDEX SYSTEM只能重建当前数据库的索引, 因此其参数必须匹配当前数据库的名字。
这是一个废弃的选项,如果声明,会被忽略。
如果你怀疑一个用户表上的索引崩溃了,你可以简单地使用REINDEX INDEX 重建该索引,或者使用REINDEX TABLE重建该表上的所有索引。
如果你从一个崩溃的系统表索引上恢复,事情会更棘手一些。这种情况下, 系统必须不能使用任何有疑问的索引。实际上,在这种情况下, 你可能发现服务器进程在启动之后马上就崩溃了,因为依赖于崩溃了的索引。要想安全恢复, 服务器必须带着-P选项启动,它禁止服务器在查找系统表的时候使用索引。
达到这个目的的一个方法是停止服务器然后带着-P 命令行选项启动一个独立的PostgreSQL服务器。然后, 根据你希望恢复的程度,发出REINDEX DATABASE, REINDEX SYSTEM, REINDEX TABLE, REINDEX INDEX命令。如果还有怀疑, 使用REINDEX SYSTEM选择重新构造数据库中全部的系统索引。 然后退出独立服务器会话并且重启普通的服务器。参阅postgres 手册页获取有关如何与独立服务器交互的信息。
另外,一个普通的会话可以在其命令行选项里使用-P选项启动。 这么做的方法因不同的客户端而异,但是在所有基于libpq的客户端上, 都可以通过在启动客户端之前设置PGOPTIONS环境变量为-P来实现。 请注意尽管这个方法并不要求锁住其它客户端,但是禁止其它客户端连接受损的数据库, 直到完成修补是一个明智的选择。
REINDEX类似于删除并重建索引,表现在它们都是从零开始重建。不过, 从锁的角度考虑,两者是有区别的。REINDEX锁住对索引的父表的写操作, 但是不锁读操作。并且它还在被处理的特定索引上保持一个排他锁, 这样它将阻止试图使用该索引的读操作。相比之下,DROP INDEX 在父表上短暂的保持一个排他锁,同时锁住读和写。随后的CREATE INDEX 锁住写操作但是不会锁住读操作;因为索引还不存在,所以不会有试图使用它的读操作, 意味着操作中不会有阻塞,只不过读操作会被迫只能使用顺序扫描。
对一个索引或者表进行重建索引,要求你是该索引或者表的所有者。 对一个数据库重建索引要求你是该数据库的所有者(注意,可以重建其它用户拥有的索引)。 当然,超级用户总是可以重建所有索引。
PostgreSQL 8.1之前,REINDEX DATABASE 只处理系统索引,而不是人们从名字猜测的那样,处理所有索引。这个行为现在已经改变了, 以减少意外的因素。旧的行为可以通过REINDEX SYSTEM获得。
PostgreSQL 7.4之前,REINDEX TABLE 并不自动处理 TOAST 表,因此这些表必须用独立的命令进行处理。这么做仍然可以, 但是已经多余了。
重建一个单独的索引:
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