utf8_general_ci 和 utf8_unicode_ci 有什么区别
-
12-09-2019 - |
题
之间 utf8_general_ci
和 utf8_unicode_ci
, ,在性能方面有什么区别吗?
解决方案
这两个排序规则均为UTF-8character encoding.差异是在文本的分类和比较。
注:由于MySQL5.5.3你应该使用 utf8mb4
而不是 utf8
.他们两个参考UTF-8编码,但是旧的 utf8
有一个MySQL-具体的限制,防止使用的字符编号为上述0xFFFD.
关键的差异
utf8mb4_unicode_ci
是基于官方Unicode的规则的普遍分类和比较,这种精确地在一个广泛的语言。utf8mb4_general_ci
是一套简化的排序规则,其目的是要做到,以及它可以同时采取了许多短期削减的设计,以改善的速度。这并不是Unicode的规则,并将导致所不希望的排序或比较,在某些情况下,例如在使用特别的语言或人物。在现代服务,这个性能的提高将所有,但是可以忽略不计。它被设计在当时的服务器了一小部分的性能,今天的计算机。
注:还有现在存在的一个更新的版本 utf8mb4_unicode_ci
叫 utf8mb4_0900_ai_ci
-这是基于改变Unicode9.0版,并且也显然是更快。它采用了一个新的方案,借此命名 0900
是Unicode版和 ai
装置的口音,不像以前 utf8mb4_unicode_ci
, ,口音的字母都不认为是显着的。
好处 utf8mb4_unicode_ci
在 utf8mb4_general_ci
utf8mb4_unicode_ci
, ,其使用Unicode规则的分类和比较,采用了一个相当复杂的算法进行正确的排序在一个范围广泛的语言和当使用一个范围广泛的特殊字符。这些规则需要考虑到语言的特定公约;不是每个人都各自己的角色,在我们称之为'字母顺序'.
尽拉丁(即"欧洲")语言去,没有太多的差别之间的Unicode的排序和简化 utf8mb4_general_ci
排序在MySQL,但仍有一些差别:
例如,Unicode的排序规则的各种"β"喜欢"ss",以及"设备"像"奥斯特的"因为人们使用这些字符,通常会想,而
utf8mb4_general_ci
各种各样它们作为单个字符的(据推测,如"s"和"e"类别)。一些Unicode的人物都被定义为可以忽略,这意味着他们不应该计入的排序和比较,应该移到下一个角色来代替。
utf8mb4_unicode_ci
处理这些正常。
在非拉丁语言,如亚洲语言或语言与不同的字母,可能有很多 更多 之间的差异Unicode的排序和简化 utf8mb4_general_ci
排序。适用性 utf8mb4_general_ci
将在很大程度上取决于使用的语言。对于某些语言,这将是相当不够的。
你应该怎么使用?
那里是几乎可以肯定没有理由使用 utf8mb4_general_ci
是了,因为我们留下点CPU速度低足够的性能差异很重要。你的数据库将几乎肯定会限制通过其他瓶颈。
在过去,有些人建议使用 utf8mb4_general_ci
除了当准确的排序将是重要的,足以证明性能的成本。今天,这一性能的费用已经全部消失,并开发对待国际化更加严重。
有一种论点被提出,如果速度更重要的是你不准确,你可能也不做任何排序在所有。这是微不足道要做一个算法的更快,如果你不需要它是准确的。所以, utf8mb4_general_ci
是一种妥协,可能不需要为速度原因,或许也不适合用于精确性的原因。
其他一件事我会加入,甚至如果你知道你的应用程序只能支持英语言,则可能仍需要处理与人的名字,而这往往包含字中使用的其他语言,其中它仅仅是作为重要的排序正确。使用Unicode的规则对于一切有助于增加平和的心态,非常聪明的Unicode人民已经非常努力地工作,使分类正常工作。
什么零件意味着
首先, ci
是为了 情况不敏感的 分类和比较。这意味着它是适合的文本数据,情况并不重要。其他类型的排序规则 cs
(case-sensitive)为文本数据的情况下是重要的, bin
, 为那里的编码的需求相匹配,位到位,其适用领域的这是真的二进制编码数据的数据(其中包括,例如,Base64)。情况敏感的排序导致一些奇怪的结果和情况敏感的比较可能导致重复的价值观不同的只是字母的情况下,这样的情况下敏感的排序规则下降了有利于对文本的数据-如果情况是显着你,然后否则可忽略的标点符号等是很可能也是重要的,而一个二元的排序规则可能更合适。
接下来, unicode
或 general
指的是具体的分类和比较的规则,特别是,文本的方式是归一化,或者相比较。有许多不同的规则为utf8mb4字符编码, unicode
和 general
是两个,试图工作,以及在所有可能的语言,而不是一个具体之一。之间的差异,这两套规则是受这个答案。请注意,新的规则,包括集 0900
参见Unicode9.0, unicode_520
参见Unicode5.2.
和最后, utf8mb4
当然是字符编码在内部使用。在这个回答我说只有基于Unicode的编码。
其他提示
我想知道什么是业绩之间的差异使用 utf8_general_ci
和 utf8_unicode_ci
, 但是我没有发现任何基准以上列出的互联网,所以我决定创建的标准我自己。
我创建了一个非常简单的表500,000行:
CREATE TABLE test(
ID INT(11) DEFAULT NULL,
Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
然后我就随机数据,通过运行这种储存程序:
CREATE PROCEDURE randomizer()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE random CHAR(20) ;
theloop: loop
SET random = CONV(FLOOR(RAND() * 99999999999999), 20, 36);
INSERT INTO test VALUES (i+1, random);
SET i=i+1;
IF i = 500000 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END
然后我创造了以下储存过程的基准,简单 SELECT
, SELECT
与 LIKE
, 和排序(SELECT
与 ORDER BY
):
CREATE PROCEDURE benchmark_simple_select()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description = 'test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_select_like()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description LIKE '%test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_order_by()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE ID > FLOOR(1 + RAND() * (400000 - 1))
ORDER BY Description COLLATE utf8_general_ci LIMIT 1000;
SET i = i + 1;
IF i = 10 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
在存储程序上 utf8_general_ci
排序规则使用,但当然,在测试期间,我用了两个 utf8_general_ci
和 utf8_unicode_ci
.
我叫每个存储的过程中5次的每个排序规则(5次 utf8_general_ci
5倍于 utf8_unicode_ci
),然后计算的平均值。
我的结果是:
benchmark_simple_select()
- 与
utf8_general_ci
:9,957ms - 与
utf8_unicode_ci
:10,271ms
在这一基准的使用 utf8_unicode_ci
是比较慢 utf8_general_ci
由3.2%.
benchmark_select_like()
- 与
utf8_general_ci
:11,441ms - 与
utf8_unicode_ci
:12,811ms
在这一基准的使用 utf8_unicode_ci
是比较慢 utf8_general_ci
12%。
benchmark_order_by()
- 与
utf8_general_ci
:11,944ms - 与
utf8_unicode_ci
:12,887ms
在这一基准的使用 utf8_unicode_ci
是比较慢 utf8_general_ci
通过7.9%.
该帖子描述它非常漂亮。
在短:utf8_unicode_ci使用Unicode归类算法作为以Unicode标准定义的,而utf8_general_ci是一个更简单的排列顺序,这导致“较不准确的”排序结果
请参阅MySQL手册, Unicode字符集一>部分:
有关任何Unicode字符集, 操作使用进行 _general_ci整理比对_unicode_ci整理得更快。 例如,对于比较 utf8_general_ci整理更快, 但略低于正确的,比 比较了utf8_unicode_ci。该 原因是, utf8_unicode_ci支持这样的映射 作为扩展;也就是说,当一个 字符作为比较等于 的其它字符的组合。对于 例如,在德国和其他一些 语言“SS”等于“SS”。 utf8_unicode_ci也支持 收缩和忽略的人物。 utf8_general_ci是遗留核对 不支持扩展, 收缩,或可忽略的字符。 它只能让一个对一 字符之间的比较。
因此,为了总结,utf_general_ci使用更小和更正确的(根据标准)组比utf_unicode_ci其中比较的应实现整个标准。该general_ci集将更快,因为有较少的计算做。
<强>在简短的话:强>
如果您需要更好的排序顺序 - 使用utf8_unicode_ci
(这是优选的方法),
但如果你完全感兴趣的性能 - 使用utf8_general_ci
,但要知道,这是一个有点过时
在性能方面的差别是非常轻微的。
一些细节(PL)
正如我们可以读到的 这里 (彼得·古鲁赞)在排序/比较波兰语字母“Ł”(带有笔划的 L - html esc)时存在差异: Ł
)(小写:“ł”-html esc: ł
) - 我们有以下假设:
utf8_polish_ci Ł greater than L and less than M
utf8_unicode_ci Ł greater than L and less than M
utf8_unicode_520_ci Ł equal to L
utf8_general_ci Ł greater than Z
波兰语字母 Ł
在字母之后 L
和之前 M
. 。这些编码中没有一种是更好或更差 - 这取决于您的需求。