utf8_general_ci
和utf8_unicode_ci
之间,在性能上是否有区别?
这两种整理方式都是针对UTF-8字符编码的。 区别在于如何对文本进行排序和比较。
注意:你应该使用utf8mb4
而不是utf8
。 它们都是指UTF-8编码,但旧的utf8
有一个MySQL特定的限制,防止使用编号高于0xFFFD的字符。
注意:较新版本的MySQL有更新的Unicode排序规则,可以用诸如 "utf8mb4_0900_ci "这样的名字来表示基于Unicode 9.0的规则,而没有相应的 "通用 "变体。
主要区别
utf8mb4_unicode_ci
是基于官方的Unicode规则,用于通用排序和比较,在各种语言中准确排序。utf8mb4_general_ci
是一套简化的排序规则,旨在尽可能地做好,同时采取许多旨在提高速度的捷径。 它不遵循Unicode规则,在某些情况下会导致不理想的排序或比较,例如在使用特定语言或字符时。
在现代服务器上,这种性能提升将是完全可以忽略不计的。 它是在服务器的CPU性能只有今天电脑的一小部分的时候设计的。
注意:现在有一个utf8mb4_unicode_ci
的更新版本,叫做utf8mb4_0900_ai_ci
- 这是基于Unicode 9.0版本的变化,显然也更快。 它采用了一个新的命名方案,即0900
是Unicode版本,ai
表示重音不敏感--像以前的utf8mb4_unicode_ci
一样,字母中的重音不被视为重要的。
utf8mb4_unicode_ci
比utf8mb4_general_ci
的好处
utf8mb4_unicode_ci
,使用Unicode规则进行排序和比较,采用了相当复杂的算法,在广泛的语言和使用广泛的特殊字符时进行正确排序。这些规则需要考虑到特定语言的习惯;不是每个人都按我们所说的字母顺序排序。
就拉丁语(即欧洲语言)而言,Unicode排序和MySQL中简化的 "utf8mb4_general_ci "排序之间没有太大区别,但仍有一些区别。utf8mb4_general_ci
将它们作为单个字符排序(估计分别像"s"和"e")。utf8mb4_unicode_ci
可以正确处理这些字符。
在非拉丁语系语言中,如亚洲语言或不同字母的语言,Unicode排序和简化的utf8mb4_general_ci
排序之间可能会有很多*多的差异。 utf8mb4_general_ci
的适用性将在很大程度上取决于所使用的语言。 对于某些语言来说,它将是相当不合适的。
你应该使用什么?
几乎可以肯定的是,没有理由再使用utf8mb4_general_ci
,因为我们已经抛开了CPU速度低到足以使性能差异变得重要的问题。 你的数据库几乎肯定会受到其他瓶颈的限制,而不是这个。
在过去,有些人建议使用utf8mb4_general_ci
,除非准确的排序足够重要,以证明性能成本的合理性。 今天,这种性能成本已经完全消失了,开发者也更加认真地对待国际化问题。
有一种说法是,如果速度对你来说比准确度更重要,你可能根本就不会做任何排序。 如果你不需要它是准确的,那么让算法更快就是小事一桩。 因此,"utf8mb4_general_ci "是一种妥协,可能因为速度的原因不需要,也可能因为准确性的原因不适合。
我还要补充一点,即使你知道你的应用程序只支持英语,它可能仍然需要处理人名,而人名往往包含其他语言的字符,正确排序也同样重要。 使用Unicode规则来处理所有的事情,有助于让人放心,因为非常聪明的Unicode人已经非常努力地使分类工作正常进行了。
这些部分意味着什么*
首先,ci
是用于不区分大小写的*排序和比较。 这意味着它适用于文本数据,大小写并不重要。 其他类型的排序是 "cs"(大小写敏感),适用于大小写重要的文本数据,以及 "bin",适用于编码需要逐位匹配的情况,适用于真正编码的二进制数据(包括,例如,Base64)。 对大小写敏感的排序会导致一些奇怪的结果,对大小写敏感的比较会导致仅有字母大小写差异的重复值,所以对大小写敏感的排序在文本数据中不再受欢迎--如果大小写对你很重要,那么其他可忽略的标点符号等可能也很重要,二进制排序可能更合适。
接下来,"unicode "或 "general "指的是具体的排序和比较规则--特别是文本被规范化或比较的方式。 utf8mb4字符编码有许多不同的规则集,"unicode "和 "general "是两个试图在所有可能的语言中工作良好的规则,而不是一个特定的规则。 这两套规则之间的差异是本答案的主题。 请注意,unicode
使用Unicode 4.0的规则。 最近版本的MySQL增加了规则集unicode_520
,使用Unicode 5.2的规则,以及0900
(去掉"unicode_" 部分),使用Unicode 9.0的规则。
最后,utf8mb4
当然是内部使用的字符编码。 在这个答案中,我只谈基于Unicode的编码。参见mysql手册,Unicode字符集部分。
对于任何Unicode字符集。 使用 _general_ci整理的操作比_unicode_ci整理的操作要快。 例如,对 utf8_general_ci整理法的比较要快。 但正确率稍低,比 utf8_unicode_ci的比较。其 的原因是 utf8_unicode_ci支持的映射,如 作为扩展;也就是说,当一个 字符比较起来等于 其他字符的组合。对于 例如,在德语和其他一些 语言中"ß "等于 "ss"。 utf8_unicode_ci还支持 缩略语和可忽略的字符。 utf8_general_ci是一种传统的整理方式 它不支持扩展。 缩略语或可忽略的字符。 它只能进行一对一的 在字符之间进行比较。
所以总结一下,utf_general_ci使用的比较集比utf_unicode_ci小,而且不那么正确(根据标准),后者应该*实现整个标准。general_ci集会更快,因为有更少的计算要做。