在重新索引时避免表锁定

Fra*_*ake 1 postgresql postgresql-10

我们使用的是 PostgreSQL 10,我们需要重新索引表以重新组织数据和可用空间。

我们遇到的问题是此操作锁定了我们需要始终保持可用的表。

我们找到了一个解决方法,但这似乎比标准释放的空间少得多reindex,所以我们将其关闭。

是否有一些解决方案可以让我们重新索引,并使表格始终可用?

Pat*_*zek 5

https://www.postgresql.org/docs/10/sql-reindex.html 上的PostgreSQL 文档说明 如下:

REINDEX 类似于索引的删除和重新创建,因为索引内容是从头开始重建的。然而,锁定的考虑是相当不同的。REINDEX 锁定索引的父表的写入而不是读取。它还对正在处理的特定索引进行排他锁,这将阻止尝试使用该索引的读取。相比之下,DROP INDEX 会暂时对父表进行排他锁,从而阻止写入和读取。随后的 CREATE INDEX 锁定写入但不锁定读取;由于索引不存在,没有读取会尝试使用它,这意味着不会有阻塞,但读取可能会被迫进行昂贵的顺序扫描。

因此,根据您的要求,您可以更改REINDEXDROP INDEX+ CREATE INDEX,这就是Pg::Reindex您链接到的内容。

关于为什么REINDEX对 B 树索引有用的相关 PostgreSQL 文档重申了这个想法(在https://www.postgresql.org/docs/10/routine-reindex.html):

REINDEX 在所有情况下都可以安全、轻松地使用。但是由于该命令需要排他表锁,因此通常最好使用一系列创建和替换步骤来执行索引重建。支持带有 CONCURRENTLY 选项的 CREATE INDEX 的索引类型可以通过这种方式重新创建。如果成功并且结果索引有效,则可以使用 ALTER INDEX 和 DROP INDEX 的组合将原始索引替换为新构建的索引。当索引用于强制唯一性或其他约束时,可能需要 ALTER TABLE 将现有约束与由新索引强制执行的约束交换。在使用这种替代的多步重建方法之前,请仔细查看它,因为可以通过这种方式重新索引哪些索引存在限制,并且必须处理错误。

除此之外,经典的方法是创建一个新表,将数据复制到其中,对其进行索引,然后重命名它以代替旧表。当然,您需要在这段时间内正确处理访问以及所有同步错误。

更一般地说,您如何计算每种方法获得的可用空间,并且您使用autovacuum得当吗?您是否真的连续受到空间的限制,以至于需要定期进行重新索引?否则,您可以在其他维护时段安排它。