©
本文档使用 PHP中文网手册 发布
REINDEX { INDEX | TABLE | DATABASE | SYSTEM } name [ FORCE ]
REINDEX使用表中的数据重建索引。使用REINDEX有两个主要原因:
索引崩溃,并且不再包含有效的数据。尽管理论上这是不可能发生的, 但实际上索引会因为软件毛病或者硬件问题而崩溃。 REINDEX提供了一个恢复方法。
索引变得"臃肿",包含大量的空页或接近空页。这个问题在某些罕见访问模式时会发生在B-tree索引上。 REINDEX通过写一个不带无用索引页的新索引提供了缩小索引空间消耗的途径。参阅Section 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锁住写操作但是不会锁住读操作;因为索引还不存在 ,所以不会有试图使用它的读操作,意味着操作中不会有阻塞,只不过读操作会被迫只能使用顺序扫描。 另外一个重要的环节是删除/重建的方法让所有使用索引的缓冲的查询规划都失效,而REINDEX不会。
对一个索引或者表进行重建索引,要求你是该索引或者表的所有者。对一个数据库重 建索引要求你是该数据库的所有者(注意,可以重建其它用户拥有的索引)。当然,超级 用户总是可以重建所有索引。
PostgreSQL 8.1之前,REINDEX DATABASE只处理系统索引,而不是人们从名字猜测的那样, 处理所有索引。这个行为现在已经改变了,以减少意外的因素。旧的行为可以通过REINDEX SYSTEM获得。
PostgreSQL7.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
SQL标准里没有REINDEX命令。