同一个 MariaDB 列的多个排序规则?

Posted

技术标签:

【中文标题】同一个 MariaDB 列的多个排序规则?【英文标题】:Multiple collations for the same MariaDB column? 【发布时间】:2018-02-19 06:43:04 【问题描述】:

当需要不同的排序规则时,如何根据文化有效地对字符串列执行 ORDER BY?也就是说,来自不同文化的用户的数据存储在同一个表和同一列中,但每个用户自然希望看到根据其语言环境排序的数据(语言环境当然是已知的,并且在表中的每一行都是固定的)。并且表可能很长,因此列需要和索引,并且不能在应用程序端进行后处理到所需的排序规则(这是数据库任务做繁重的工作,对吧?)。

例如,utf8_general_ci 产生与 utf8_swedish_ci 不同的结果。

虽然我认为这个问题对于任何国际项目都应该是显而易见的,但我找不到任何合适的解决方案。我自己只能想象以下解决方案,它们不是很好,我怀疑没有更好的办法:

    为每个排序规则使用单独的字段 也许,可以为每种文化创建一个视图并进行相应的索引(虽然我没有使用过 MariaDB 视图,所以这是相当理论的) 使用单独的“代理”字段进行排序,可能是 VIRTUAL

现在,如果只有一个可排序的字符串列,但可能有多个。解决此问题的预期和正确方法是什么?

【问题讨论】:

【参考方案1】:

只要您使用相同的字符集(在您的情况下为utf8)进行列存储和读取,您就可以在ORDER BY column-name 子句之后使用COLLATE some-utf8-collation

SELECT * FROM sometable ORDER BY somecolumn COLLATE utf8_swedish_ci

在我的测试中,这会产生与德国排序规则不同的排序:

SELECT * FROM sometable ORDER BY somecolumn COLLATE utf8_german2_ci

好吧,只要数据包含相关字符,例如德语变音符号üöä。否则,您将看不到任何差异。

ORDER 子句中的多个列各有自己的COLLATE 术语:

SELECT * FROM sometable
ORDER BY
    somecolumn COLLATE utf8_german2_ci,
    secondcolumn COLLATE utf8_german2_ci

【讨论】:

这适用于“小”表。添加COLLATE 子句会阻止使用任何INDEX,因为索引已经在特定的排序规则中。 哦,是的,没错。 EXPLAINCOLLATE 子句中使用不同的排序规则时表示“使用索引,使用文件排序”。好吧,在这种情况下,应该找到一种方法来复制所需排序规则中的相关列,同时在填充时尽量减少工作量。虚拟列在这里没有帮助,因为他们无法获得INDEX,而持久列可以,但EXPLAIN 表示它始终在SELECT 中使用文件排序。因此,您最终将使用所需的排序规则手动填充其他列。嗯,更糟。 文件排序发生的原因有很多;看具体查询和CREATE TABLE讨论吧。 即使对于带有索引的最简单的字符串列(无论使用或省略什么排序规则),也无法摆脱文件排序。虽然这个答案现在已经足够好了(谢谢!),但我希望得到一个涵盖使用索引进行排序的答案。但我也在使用限制,所以也许这是相关的:mariadb.com/kb/en/library/…

以上是关于同一个 MariaDB 列的多个排序规则?的主要内容,如果未能解决你的问题,请参考以下文章

JPA + MariaDB:排序规则如何影响 unicode 支持?

在 SQL 2005 中更改聚集索引列的排序规则

字符集和排序规则会影响 MySQL/MariaDB 中的查询性能吗?

发现 MySQL 列的排序规则

翻译:MariaDB字符集和排序规则

如何使用 SQL 设置列的排序规则?