Christoph Schiessl:使用 `REINDEX` 修复损坏的索引

Christoph Schiessl:使用 `REINDEX` 修复损坏的索引

💡 原文英文,约1000词,阅读约需4分钟。
📝

内容提要

本文讨论了在PostgreSQL中修复因错误声明IMMUTABLE函数导致的索引损坏问题。通过创建自定义ENUM类型和相应的索引,展示了ENUM值重命名后查询结果的不一致性。解决方案是使用REINDEX重建损坏的索引,强调在定义自定义函数时要谨慎,避免将函数的波动性类别设置得过于严格。

🔎

延伸解读

错误声明 IMMUTABLE 的根源

文章指出,将函数声明为 IMMUTABLE 意味着 PostgreSQL 认为其输出仅依赖于输入参数。但示例中的 marital_status_as_text 函数封装了 ENUM 到 TEXT 的类型转换,而该转换的结果取决于 ENUM 值的名称,名称可被 ALTER TYPE 重命名,因此函数并非真正 IMMUTABLE。这种错误声明导致索引与表数据不同步,是索引损坏的根本原因。

索引损坏后的不一致表现

ENUM 值重命名后,基于 ENUM 的查询能返回正确结果,而基于 TEXT 转换的查询却返回空集。更严重的是,同一查询在强制使用索引和强制顺序扫描时结果不同,因为索引中存储的是旧值。这种不一致性正是索引损坏的典型症状,也说明查询计划可能影响结果,给调试带来困难。

REINDEX 的修复与局限

使用 REINDEX INDEX 命令可以重建损坏的索引,使其与表数据重新同步。文章演示了重建后查询结果恢复一致。但 REINDEX 仅修复症状,不解决根本原因:如果再次重命名 ENUM 值,问题会重现。因此,修复后仍需修正函数声明或避免此类设计。

定义自定义函数的注意事项

文章强调,定义自定义函数时必须确保波动性类别与实际相符。将非 IMMUTABLE 的函数错误声明为 IMMUTABLE,可能被用于创建索引,进而因外部因素变化导致索引损坏。开发者应谨慎评估函数是否真正引用透明,避免为满足索引创建条件而过度收紧波动性声明。

❓

Q&A

如何在PostgreSQL中修复损坏的索引?

可以使用REINDEX命令重建损坏的索引,以确保索引与表数据同步。

定义IMMUTABLE函数时需要注意什么?

在定义IMMUTABLE函数时需谨慎,避免错误声明,以免导致索引损坏。

ENUM值重命名会导致什么问题?

ENUM值重命名可能导致查询结果不一致,因为索引与表数据不同步。

为什么会出现索引与数据不同步的情况?

因为错误声明IMMUTABLE函数,导致索引未能正确反映数据的变化。

REINDEX命令的作用是什么?

REINDEX命令用于重建损坏的索引,使其与表数据保持一致。

在定义自定义函数时应如何设置波动性类别?

应确保函数的波动性类别与实际情况相符,避免设置得过于严格。

🏷️

标签

➡️

继续阅读