使用二进制排序规则会产生哪些影响?

59

回答此问题时,我开始对一个问题感到不确定,并没有找到足够的答案。

utf8_bin和不区分大小写的utf8_general_ci排序规则之间有哪些实际差异?

我能看到三个方面:

  1. 两者具有不同的排序顺序; _bin的排序顺序可能会将任何umlauts放在字母表的末尾,因为比较的是字节值(对吧?)

  2. 只有对大小写敏感的搜索在_bin

  3. _bin中没有A = Ä的相等性

还有其他需要注意的差异或副作用吗?

参考:

类似但并未解决问题的问题:

4个回答

76

二进制排序法会完全按照C语言中的strcmp()方法比较您的字符串,如果字符不同(无论是大小写差异还是音标差异),则会将其视为不同。它的缺点是排序顺序不自然。

“二进制”排序顺序的示例: A,B,a,b 在自然排序顺序中,例如:A,a,B,b(相同字母的大小写变体会排在一起)

二进制排序法的实际优势在于速度快,因为字符串比较非常简单/快速。在一般情况下,使用二进制索引可能无法产生期望的排序结果,但对于精确匹配,它们可能是有用的。


谢谢提供这些示例,它们很好地说明了问题。 - Pekka
如果我需要对非常大的表(数据量超过400万条)进行区分大小写的比较怎么办?最近我遇到了这个问题,使用utf_8_unicode_ci排序规则时,我的查询在性能方面表现良好,但无法产生精确匹配。如果我将排序规则更改为utf8_bin,则性能会急剧下降...这在性能方面有很大的差异。 - shashi009
3
以上内容需要进行小修正..它与strcmp()函数几乎相同,但并非100%完全相同。根据SQL标准,不同长度的字符串需要按照短字符串通过空格字符(0x20)进行填充直到达到更长的字符串的长度进行比较。在大多数情况下,这将像strcmp()一样运行,但在包含字节<0x20(空格)的退化情况中,它则不能。例如,'a\t'(后面跟了一个TAB键的'a')小于'a '(后面跟了一个空格的'a'),因此'a\t'<'a'。MariaDB 10.2引入了NOPAD排序规则,完全匹配strcmp()函数的行为。(https://jira.mariadb.org/browse/MDEV-9711) - Vladislav Vaintroub

20

utf8_bin: 比较字符串时会通过每个字符的二进制值进行比对。

utf8_general_ci: 使用一般语言规则,并且忽略大小写来比较字符串。

utf8_general_cs: 使用一般语言规则,但区分大小写来比较字符串。

例如,以下内容无论使用哪种 UTF8_general 编码都会返回 true,但不适用于 utf8_bin 编码:

Ä = A Ö = O Ü = U

而使用 utf8_general_ci 编码时,即使大小写不同,它们也将返回 true。 http://www.phpbuilder.com/board/showpost.php?s=2e642ac7dc5fceca2dbca1e2b9c424fd&p=10820221&postcount=2


2
*_cs 是否比 *_ci 更快?适用于英文/ASCII字符串。 - Yousha Aleayoub

2
其他答案已经很好地解释了差异。
在某些情况下,二进制排序规则可能会很有用:
- 列包含十六进制数据,例如密码哈希值 - 您只对精确匹配感兴趣,而不是排序 - 对于仅包含 [a-z0-9_] 字符的标识符,您甚至可以将其用于排序 - 如果由于某种原因在 CHAR() 或 VARCHAR 列中存储数字(例如电话号码) - 邮政编码 - UUIDs - 等等
在所有这些情况下,您都可以通过使用二进制排序规则来节省一点 CPU 周期。

二进制类型是什么?ascii_bin、utf8_bin、latin1_bin等等...? - Yousha Aleayoub

1

使用utf8_general_ci,匹配不区分大小写和重音符号。当您需要对单词执行查询时,这可能是一件好事。

utf8_bin中,仅当字符串严格相同时才匹配。这种方式的查询速度更快。


utf8_bin比latin1_bin或ascii_bin更快吗? - Yousha Aleayoub
2
不过,**_bin** 应该比 _ci 更快,因为大小写不敏感的查询(或索引)涉及字符串转换。了解速度更快的最好方法是针对包含许多条目的数据库进行测试。 - Mathieu Rodic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接