国际数据库如何选择排序规则?

Tae*_*Tae 25 postgresql index database-design collation

我正在设计一个以不同语言存储数据的数据库(使用 UTF-8),所以我认为显示查询结果的最佳方式是在查询期间根据用户的语言对其进行排序(因为有多个正确的方法来做到这一点),如下:

SELECT a < b COLLATE "de_DE" FROM test1;
Run Code Online (Sandbox Code Playgroud)

假设这是处理国际数据的正确方法,那么对于数据库本身来说,哪种整理是最好的呢?PostgreSQL 文档说

C 和 POSIX 排序规则都指定了“传统的 C”行为,其中只有 ASCII 字母“A”到“Z”被视为字母,并且严格按照字符代码字节值进行排序。

我认为这是这种情况下的最佳选择,还是我错了?

(额外的问题:在查询本身中选择排序规则是否太慢?)。

Erw*_*ter 30

C整理是正确的选择。

没有语言环境,一切都会快一点。并且由于无论如何都没有正确的排序规则,因此创建没有排序规则的数据库,意思是使用C.

必须为许多操作提供排序规则可能会很痛苦。但是,默认排序规则和临时排序规则之间的速度不应有明显差异。毕竟它只是未排序的数据,排序时应用了整理规则。

请注意,Postgres 建立在底层操作系统提供的语言环境设置上,因此您需要为要使用的每个语言环境生成语言环境。更多关于 SO herehere 的相关答案

但是,正如@Craig 已经提到的索引是这种情况下的瓶颈。在许多涉及字符数据的情况下,索引的排序规则必须与应用的运算符的排序规则相匹配。

您可以COLLATE在索引中使用说明符来生成匹配索引。部分索引如果您在同一个表中混合数据,可能是完美的选择。

例如,具有国际字符串的表:

CREATE TABLE string (
   string_id serial
  ,lang_id   int NOT NULL
  ,string    text NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

并且您一次只对一种语言感兴趣:

SELECT *
FROM   string
WHERE  lang_id = 5  -- 5 being German / Germany here
AND    string > 'foo' COLLATE "de_DE"
ORDER  BY string COLLATE "de_DE";
Run Code Online (Sandbox Code Playgroud)

然后创建部分索引,如:

CREATE INDEX string_string_lang_id_idx ON string (string COLLATE "de_DE")
WHERE lang_id = 5;
Run Code Online (Sandbox Code Playgroud)

您需要的每种语言都有一个。

实际上,对于像这样的表,继承可能是一种更好的方法。然后,您可以在每个继承的表上创建一个纯索引,该索引仅包含单个语言环境的字符串。当然,您需要熟悉继承表的特殊规则。


Pet*_*aut 14

我建议您选择提供默认 Unicode 排序的排序规则。这样,即使您不覆盖每个查询中的排序规则,您也会获得合理的结果。不幸的是,大多数(全部?)操作系统不提供简单命名为“默认 Unicode”或类似名称的语言环境,因此您必须猜测和/或研究一个不错的选择。例如,在 Linux/glibc 上,de_DE.utf8 或 en_US.utf8 语言环境只是通过默认行为,所以这两个都是不错的选择。

我不认为使用 C 语言环境是一个好主意,因为那样你的应用程序的默认行为将毫无用处。而且您可能无法从大小写转换操作中获得正确的行为。

(覆盖查询中的排序规则没有太多开销。这只是一个解析时操作。)

  • 目前我正在测试数据库中使用 es_CL.utf8 ,但是由于您的回答,我多看了一点,发现 [`utf8_unicode_ci` 是可行的方法](http://stackoverflow.com/questions/766809/ utf8-general-ci 和 utf8-unicode-ci 之间的区别是什么)。 (2认同)