Postgresql 中文操作指南
Synopsis
REINDEX [ ( option [, ...] ) ] { INDEX | TABLE | SCHEMA } [ CONCURRENTLY ] name
REINDEX [ ( option [, ...] ) ] { DATABASE | SYSTEM } [ CONCURRENTLY ] [ name ]
where option can be one of:
CONCURRENTLY [ boolean ]
TABLESPACE new_tablespace
VERBOSE [ boolean ]
Parameters
-
INDEX
-
重新创建指定的索引。当与分区索引一起使用时,此形式的 REINDEX 不能在事务块中执行。
-
-
TABLE
-
重新创建指定表的全部索引。如果该表包含辅助“TOAST”表,那么该表也将重新编制索引。当与分区表一起使用时,此形式的 REINDEX 不能在事务块中执行。
-
-
SCHEMA
-
重新创建指定架构中的全部索引。如果该架构的表包含辅助“TOAST”表,那么该表也将重新编制索引。共享系统目录的索引也将得到处理。此形式的 REINDEX 不能在事务块中执行。
-
-
DATABASE
-
重新创建当前数据库中的全部索引,但系统目录除外。系统目录上的索引不被处理。此形式的 REINDEX 不能在事务块中执行。
-
-
SYSTEM
-
重新创建当前数据库中的全部系统目录索引。包含共享系统目录的索引。用户表上的索引不被处理。此形式的 REINDEX 不能在事务块中执行。
-
-
name
-
要重新编制索引的特定索引、表或数据库的名称。索引和表名称可以经过架构限定。当前, REINDEX DATABASE 和 REINDEX SYSTEM 只能重新编制当前数据库的索引。它们的参数是可选的,并且必须与当前数据库的名称匹配。
-
-
CONCURRENTLY
-
使用此选项时,PostgreSQL 将重新构建索引而不会采取任何阻止同时在该表上插入、更新或删除的锁;而标准索引重新构建会在执行完成之前,对对该表的写入(但不包括读取)进行锁定。使用此选项时需要注意几个注意事项 — 请参见下面的 Rebuilding Indexes Concurrently 。
-
对于临时表, REINDEX 始终是非并发式的,因为没有其他会话可以访问它们,并且非并发式重新编制索引更便宜。
-
-
TABLESPACE
-
指定将在新表空间上重新构建索引。
-
-
VERBOSE
-
在每个索引重新编制索引时打印进度报告。
-
-
boolean
-
指定所选选项应该开启还是关闭。您可以编写 TRUE 、 ON 或 1 来启用该选项,并编写 FALSE 、 OFF 或 0 来禁用它。也可以省略 boolean 值,在这种情况下假定 TRUE 。
-
-
new_tablespace
-
将在其上重新构建索引的表空间。
-
Notes
如果您怀疑用户表上的索引已损坏,您可以使用 REINDEX INDEX 或 REINDEX TABLE 简单地重新构建该索引或该表上的全部索引。
如果您需要从系统表上索引的损坏中进行恢复,那么情况就会变得更复杂。在这种情况下,系统本身不要使用任何可疑索引非常重要。(事实上,在这种情况下您可能会发现服务器进程立即在启动时崩溃,由于依赖于损坏的索引。)为了进行安全恢复,必须使用 -P 选项启动服务器,这会阻止它使用系统目录查找的索引。
执行此操作的一种方法是关闭服务器,并通过命令行中包含 -P 选项来启动一个单用户 PostgreSQL 服务器。然后,可执行 REINDEX DATABASE 、 REINDEX SYSTEM 、 REINDEX TABLE 或 REINDEX INDEX ,具体视你需要重建的内容而定。如有疑问,请使用 REINDEX SYSTEM 以选择重建数据库中所有系统索引。然后退出单用户服务器会话并重新启动常规服务器。请参阅 postgres 参考页面以获取有关如何与单用户服务器界面进行交互的详细信息。
另外,可在其命令行选项中包括 -P 以启动常规的服务器会话。执行此操作的方法因客户端而异,但在所有基于 libpq 的客户端中,都可以在启动客户端之前将 PGOPTIONS 环境变量设置为 -P 。请注意,虽然此方法不需要锁定其他客户端,但在修复完成之前,仍建议禁止其他用户连接到损坏的数据库。
REINDEX 与 index 的删除和创建类似,因为 index 的内容是从头重建的。但是,锁定方面有所不同。 REINDEX 不会锁定写操作,但会锁定对其父表进行的读取操作。它还会对正在处理的特定索引加 ACCESS EXCLUSIVE 锁,这会阻塞尝试使用该索引的读取操作。具体来说,无论查询如何,查询计划程序都会尝试在表的每个索引上加 ACCESS SHARE 锁,因此 REINDEX 实际上会阻塞除一些计划已缓存且不使用此索引的已准备查询之外的所有查询。与之相比, DROP INDEX 会在父表上瞬间加 ACCESS EXCLUSIVE 锁,从而阻塞写操作和读取操作。 CREATE INDEX 也会阻塞写操作,但不会阻塞读取操作;由于没有索引,因此所有读取操作都不会尝试使用它,这意味着不会发生阻塞,但可能会强制将读取操作转为昂贵的顺序扫描。
对单个索引或表重新建立索引需要拥有该索引或表的权限。对模式或数据库重新建立索引需要拥有该模式或数据库的权限。特别注意,非超级用户因此可以重建其他用户拥有的表的索引。但是, REINDEX DATABASE 、 REINDEX SCHEMA 或 REINDEX SYSTEM 由非超级用户发出时,会出现一个特殊情况,其中共享目录的索引将会被跳过,除非该用户拥有该目录(通常不会这样)。当然,超级用户总是可以对任何内容重新建立索引。
通过 REINDEX INDEX 或 REINDEX TABLE 分别支持对分区索引或分区表进行重新编制索引。指定分区关系的每个分区都在单独的事务中重新建立索引。在对分区表或索引进行处理时,不能在事务块中使用这些命令。
在分区索引或表上使用 REINDEX 子句和 TABLESPACE 时,只会更新叶分区的数据表空间引用信息。由于不更新分区索引,建议在该索引上分别使用 ALTER TABLE ONLY ,以便附加的任何新分区都继承新数据表空间。如果失败,则可能无法将所有索引移至新数据表空间。重新运行该命令将重建所有叶分区,并将前述未处理的索引移至新数据表空间。
如果将 SCHEMA 、 DATABASE 或 SYSTEM 与 TABLESPACE 一起使用,则将会跳过系统关系,并且将会生成单个 WARNING 。TOAST 表的索引会重建,但不会移至新数据表空间。
Rebuilding Indexes Concurrently
重建索引可能会干扰数据库的常规操作。通常,PostgreSQL 会在写操作中针对索引重建锁定要被重建的表,并使用一次表扫描来执行整个索引构建。其他事务仍然可以读取表,但如果它们尝试在表中插入、更新或删除行,则它们将阻塞,直到索引重建完成为止。如果该系统是生产数据库,则这可能会产生严重影响。非常大的表可能需要花费很多小时才能建立索引,即使对于较小的表,索引重建也会将写操作锁定到对于生产系统而言不可接受的时间。
PostgreSQL 支持以最少的写锁定重建索引。此方法是通过指定 REINDEX 的 CONCURRENTLY 选项来调用的。使用此选项时,PostgreSQL 必须为需要重建的每个索引扫描两次表,并等待所有可能使用该索引的现有事务终止。此方法比标准索引重建需要更多总体工作,并且由于它需要等待可能修改索引的未完成事务而花费更长的时间才能完成。但是,由于此方法允许在重建索引时继续进行正常操作,因此此方法对于在生产环境中重建索引很有用。当然,索引重建强加的额外 CPU、内存和 I/O 负载可能会减慢其他操作。
并行重新建立索引中会发生以下步骤。每个步骤都在单独的事务中运行。如果有需要重建的多个索引,则每个步骤都会遍历所有索引,然后再移动到下一步骤。
如果在重建索引时出现问题,例如唯一索引中的唯一性冲突,则 REINDEX 命令将失败,但除了预先存在的索引之外,还会遗留下一个“无效”的新索引。此索引将被忽略以用于查询,因为它可能不完整;但是,它仍然会消耗更新开销。psql \d 命令将报告此类索引为 INVALID :
postgres=# \d tab
Table "public.tab"
Column | Type | Modifiers
--------+---------+-----------
col | integer |
Indexes:
"idx" btree (col)
"idx_ccnew" btree (col) INVALID
如果标记为 INVALID 的索引紧跟着 ccnew ,则它对应于在并行操作期间创建的瞬态索引,推荐的恢复方法是使用 DROP INDEX 删除它,然后再次尝试 REINDEX CONCURRENTLY 。如果无效索引紧跟着 ccold ,则它对应于无法删除的原始索引;推荐的恢复方法是只删除所述索引,因为重建本身已经成功。
常规索引构建允许在同一表上同时发生其他常规索引构建,但一次只能在表上发生一次并行索引构建。在两种情况下,在此期间都不允许对表进行其他类型的模式修改。另一个区别是可以在事务块中执行常规 REINDEX TABLE 或 REINDEX INDEX 命令,但不能在事务块中执行 REINDEX CONCURRENTLY 。
与任何长时间运行的事务一样,表上的 REINDEX 可能会影响其他任何表上的并行 VACUUM 可以移除哪些元组。
REINDEX SYSTEM 不支持 CONCURRENTLY ,因为无法并发重新建立系统目录索引。
此外,不能并发重新建立排除约束的索引。如果在此命令中直接命名了此类索引,则会引发错误。如果对具有排除约束索引的表或数据库进行并行重新建立索引,则将会跳过那些索引。(有可能在没有 CONCURRENTLY 选项的情况下重新建立此类索引)。
运行 REINDEX 的每个后端将在 pg_stat_progress_create_index 视图中报告其进度。详情请参阅 Section 28.4.4 。
Examples
重建单个索引:
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
为一个表重新构建索引,在重新索引进行时,不阻止对涉及关系的读写操作:
REINDEX TABLE CONCURRENTLY my_broken_table;