Laurenz Albe:使用“内置”C 排序规则创建你的 PostgreSQL 集群!

Laurenz Albe:使用“内置”C 排序规则创建你的 PostgreSQL 集群!

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

内容提要

PostgreSQL 默认使用外部库的语言环境排序规则,操作系统升级可能改变排序规则,导致字符串索引损坏,必须重建。建议用 C 排序规则建库:它按字节比较,只依赖字符编码,永不改变,且比较更快。若需自然语言排序,可仅在个别列或 ORDER BY 中指定其他排序规则,以减少可能损坏的索引。v17 起可用内置 C 排序规则,降低外部依赖。

🔎

延伸解读

C 排序规则的核心优势:稳定与高效

C 排序规则按字节比较字符串,仅依赖字符编码,因此排序顺序永不改变。这避免了操作系统升级导致排序规则变化,从而防止字符串索引损坏。同时,字节比较比自然语言排序更高效,能提升查询性能。对于不需要自然语言排序的场景,使用 C 排序规则可以显著降低维护成本。

自然语言排序的复杂性与风险

自然语言排序规则涉及特殊字符处理、大小写顺序等复杂逻辑,不同语言规则各异。实现中的错误修复可能导致排序规则变化,进而使索引损坏。操作系统升级可能更新外部库,改变排序行为,因此必须重建受影响索引。若必须使用自然语言排序,应尽量缩小其应用范围。

灵活使用排序规则:列级与查询级指定

即使数据库使用 C 排序规则,仍可在列定义或 ORDER BY 子句中指定自然语言排序规则。例如,为 name 列指定奥地利 ICU 排序规则,则按该列排序时自动使用,相关索引也按此排序。这样,只有少数索引可能受升级影响,减少重建需求。

PostgreSQL v17+ 的内置排序规则提供者

从 v17 开始,PostgreSQL 提供内置排序规则提供者,减少对外部库的依赖。初始版本支持 C 和 C.UTF-8,v18 增加 PG_UNICODE_FAST。这些排序规则简单且不支持自然语言,其中 C.UTF-8 和 PG_UNICODE_FAST 依赖 Unicode 版本,可能随更新变化。为完全稳定,建议使用 C 排序规则。

❓

Q&A

为什么 PostgreSQL 默认排序规则会导致索引损坏?

PostgreSQL 默认使用外部库(C 库或 ICU 库)提供的语言环境排序规则。操作系统升级会升级这些库,有时会改变排序规则,导致字符串索引排序错误,即索引损坏。

C 排序规则有什么优点和缺点?

优点:按字节比较,只依赖字符编码,排序顺序永不改变,且比较速度更快。缺点:排序顺序不符合自然语言习惯,例如大写字母排在小写字母之前,非 ASCII 字符排在 ASCII 字符之后。

如何在使用 C 排序规则的同时实现自然语言排序?

可以在列定义时指定其他排序规则,或在 ORDER BY 子句中显式指定排序规则。这样只有这些列上的索引可能受操作系统升级影响,减少了需要重建的索引数量。

PostgreSQL v17 及以上版本提供了哪些内置排序规则?

v17 引入了内置排序规则提供者,初始提供 C 和 C.UTF-8;v18 增加了 PG_UNICODE_FAST。这些排序规则简单且不支持自然语言,其中 C.UTF-8 和 PG_UNICODE_FAST 依赖 Unicode 版本,可能随 PostgreSQL 更新而变化,因此推荐使用 C。

如何使用内置 C 排序规则创建数据库集群?

使用 initdb 并指定选项,例如:initdb --locale-provider=builtin --locale=C -D /path/to/data。也可以创建数据库时指定内置 C 排序规则,但若集群默认语言环境不同,需使用 template0 作为模板。

使用 C 排序规则能带来哪些性能优势?

C 排序规则的字符串比较比自然语言排序规则更廉价,因为只需简单的 memcmp() 调用,从而提升查询性能。

🏷️

标签

➡️

继续阅读