内容提要
本文讨论了Postgres、Db2、SQL Server和Oracle等SQL数据库的默认排序规则和语言排序的使用。Postgres的最佳默认排序规则是基于字符编码的排序,语言排序可以通过SQL语句进行。Db2和Oracle也采用了类似的默认排序规则。SQL Server默认使用与Windows Server安装语言相关的ISO-8859排序规则。Oracle的默认排序规则基于客户端连接,不同国家和地区有不同的默认排序规则。Postgres历史上依赖于外部库进行排序,但Postgres 17将添加内置排序提供程序。作者建议在应用逻辑需要时使用语言排序,而默认情况下使用基于字符编码的排序规则。
延伸解读
默认排序规则的选择:代码点顺序 vs 语言排序
作者经过调研后认为,Postgres 的最佳默认排序规则应是基于代码点的顺序,这与 Db2 和 Oracle 的做法一致。语言排序应仅在应用逻辑需要时通过 SQL 显式指定。这样做能确保系统目录始终使用代码点排序,并带来性能和稳定性优势。在现有 Postgres 版本中,可使用 C 或 C.UTF-8 排序规则;Postgres 17 将引入内置排序提供程序,提供更好的字符语义和性能。
各数据库默认排序规则的差异与影响
Db2 和 Oracle 默认使用 Unicode 编码和代码点顺序排序(分别称为 IDENTITY 和 BINARY),但 Oracle 的默认排序规则是客户端连接的属性,在某些地区会默认使用语言排序,导致 ORDER BY 与其他操作符行为不一致。SQL Server 默认使用与 Windows 安装语言相关的 8 位编码排序规则,常引发临时表与用户表之间的排序规则冲突。Postgres 历史上依赖外部库,默认排序规则由操作系统环境决定,不同系统安装可能不同。
Postgres 17 内置排序提供程序:解决旧版痛点
Postgres 17 将引入内置的排序提供程序,提供 C.UTF-8 排序规则(pg_c_utf8),它基于代码点排序,性能与 C 排序规则相当,但具备良好的非 ASCII 字符语义(如大小写转换、正则表达式、大小写不敏感比较)。这解决了旧版中必须在 C 排序规则(性能好但语义差)和 C.UTF-8 排序规则(语义好但性能较差)之间权衡的问题。内置提供程序不依赖外部库,因此更稳定、安全,且在所有平台上行为一致。
实践建议:默认代码点排序,按需语言排序
作者建议将 Postgres 数据库的默认排序规则设置为代码点顺序(仔细考虑 C 与 C.UTF-8 的区别),并在应用逻辑确实需要自然语言排序时,通过 SQL 语句指定语言排序(例如 ORDER BY colname COLLATE "unicode")。这种做法已被许多现有企业应用和数据库采用,能确保系统目录使用代码点排序,同时带来速度、性能和稳定性方面的好处。对于其他数据库,也应注意其默认排序规则可能带来的兼容性和性能问题。
Q&A
Postgres 17的默认排序规则是什么?
Postgres 17的默认排序规则是基于字符编码的排序,具体为C.UTF-8排序。
SQL Server的默认排序规则是如何确定的?
SQL Server的默认排序规则与Windows Server的安装语言相关,通常使用ISO-8859排序规则。
Oracle的排序规则是如何设置的?
Oracle的排序规则是客户端连接的属性,不同国家和地区有不同的默认排序规则。
Db2如何处理日期和数字的格式化?
Db2会根据客户端的本地化环境格式化日期和数字,但ORDER BY语句始终根据服务器设置排序。
Postgres在排序时依赖于什么?
Postgres历史上依赖于外部库进行排序,但Postgres 17将添加内置排序提供程序。
在什么情况下应该使用语言排序?
在应用逻辑需要时使用语言排序,默认情况下应使用基于字符编码的排序规则。