======= REINDEX ======= .. container:: refentry :name: SQL-REINDEX .. container:: titlepage .. container:: refnamediv .. rubric:: REINDEX :name: reindex REINDEX — 重建索引 .. container:: refsynopsisdiv .. rubric:: 大纲 :name: 大纲 .. code:: synopsis REINDEX { INDEX | TABLE | SCHEMA } name .. container:: refsect1 :name: id-1.9.3.162.5 .. rubric:: 描述 :name: 描述 ``REINDEX``\ 使用索引的表里存储的数据重建一个索引, 并且替换该索引的旧拷贝。有一些场景需要使用\ ``REINDEX``\ : .. container:: itemizedlist - 一个索引已经损坏,并且不再包含合法数据。尽管理论上这不会发生, 实际上索引会因为软件缺陷或硬件失效损坏。 ``REINDEX``\ 提供了一种恢复方法。 - 一个索引变得“臃肿”,其中包含很多空的或者近乎为空的页面。 OushuDB 中的 B-树索引在特定的非 常规访问模式下可能会发生这种情况。\ ``REINDEX`` 提供了一种方法来减少索引的空间消耗,即制造一个新版本的索引,其中没有 死亡页面。 - 修改了一个索引的存储参数(例如填充因子),并且希望确保这种修改完全 生效。 .. container:: refsect1 :name: id-1.9.3.162.6 .. rubric:: 参数 :name: 参数 .. container:: variablelist ``INDEX`` 重新创建指定的索引。 ``TABLE`` 重新创建指定表的所有索引。如果该表有一个二级 “TOAST”表,它也会被重索引。 ``SCHEMA`` 重建指定方案的所有索引。如果这个方案中的一个表有次级的“TOAST”表,它也会被重建索引。共享系统目录上的索引也会被处理。这种形式的\ ``REINDEX``\ 不能在事务块内执行。 *``name``* 要被重索引的特定索引、表或者数据库的名字。索引和表名可以被 模式限定。 对于临时表,\ ``REINDEX``\ 始终是非并发的,因为没有其他会话可以访问它们,并且非并发重新索引更便宜。 .. container:: refsect1 :name: id-1.9.3.162.7 .. rubric:: 注解 :name: 注解 如果怀疑一个用户表上的索引损坏,可以使用 ``REINDEX INDEX``\ 或者 ``REINDEX TABLE``\ 简单地重建该索引 或者表上的所有索引。 如果你需要从一个系统表上的索引损坏中恢复,就更困难一些。在 这种情况下,对系统来说重要的是没有使用过任何可疑的索引本身( 实际上,这种场景中,你可能会发现服务器进程会在启动时立刻崩溃, 这是因为对于损坏的索引的依赖)。要安全地恢复,服务器必须用 ``-P``\ 选项启动,这将阻止它使用索引来进行系统 目录查找。 这样做的一种方法是关闭服务器,并且启动一个单用户的 OushuDB 服务器,在其命令行 中包括\ ``-P``\ 选项。然后,可以发出 ``REINDEX TABLE``\ 或者\ ``REINDEX INDEX``\ , 具体使用哪个命令取决于你想要重构多少东西。 在另一种方法中,可以开始一个常规的服务器会话,在其命令行选项 中包括\ ``-P``\ 。这样做的方法与客户端有关,但是在 所有基于libpq的客户端中都可以在开始客户端 之前设置\ ``PGOPTIONS``\ 环境变量为\ ``-P``\ 。 注意虽然这种方法不要求用锁排斥其他客户端,在修复完成之前避免 其他用户连接到受损的数据库才是更加明智的。 ``REINDEX``\ 类似于删除索引并且重建索引,在其中 索引内容会被从头开始建立。不过,锁定方面的考虑却相当不同。 ``REINDEX``\ 会用锁排斥写,但不会排斥在索引的父表上的读。 它也会在被处理的索引上取得一个排他锁,该锁将会阻塞对该索引的使用尝试。 相反,\ ``DROP INDEX`` 会暂时在附表上取得一个排他锁,阻塞 写和读。后续的\ ``CREATE INDEX``\ 会排斥写但不排斥读,由于 该索引不存在,所以不会有读取它的尝试,这意味着不会有阻塞但是读操作可能 被强制成昂贵的顺序扫描。 重索引单独一个索引或者表要求用户是该索引或表的拥有者。注意因此非超级用户有时无法重建其他用户拥有的表上的索引。不过,作为一种特例,当一个非超级用户发出\ ``REINDEX SCHEMA``\ 时,共享目录上的索引将被跳过,除非该用户拥有该目录(通常不会是这样)。当然,超级用户总是可以重建所有的索引。 不支持重建分区表的索引或者分区索引。不过可以单独为每个分区重建索引。 不支持重建系统表的索引,只支持重建用户表索引。 .. container:: refsect1 :name: id-1.9.3.162.8 .. rubric:: 示例 :name: 示例 重建单个索引: .. code:: programlisting REINDEX INDEX my_index; 重建表\ ``my_table``\ 上的所有索引: .. code:: programlisting REINDEX TABLE my_table; 重建表的索引 .. code:: programlisting REINDEX TABLE my_broken_table; .. container:: refsect1 :name: id-1.9.3.162.9 .. rubric:: 兼容性 :name: 兼容性 在 SQL 标准中没有\ ``REINDEX``\ 命令。 .. container:: refsect1 :name: id-1.9.3.162.10 .. rubric:: See Also :name: see-also `CREATE INDEX `__, `DROP INDEX `__, `reindexdb `__