UTF-8和Latin1的区别

22
使用utf8和使用latin1作为字符集之间有什么优缺点?
如果utf8能支持更多字符并且始终如一地使用,它是否总是更好的选择?选择latin1是否有任何原因?

2
始终使用 utf8mb4 而非 utf8 - 这是 MySQL 的一种错误 - xmedeko
4个回答

23

UTF8优点:

  1. 支持大多数语言,包括从右到左的语言,如希伯来语。

  2. 在与支持UTF8的组件(JavaScript、Java等)导入/导出数据时不需要进行翻译。

UTF8缺点:

  1. 非ASCII字符会因其更复杂的编码方式而需要更长时间进行编码和解码。

  2. 非ASCII字符可能需要使用多个字节存储(不在ASCII字符集的前127个字符中),因此需要更多的存储空间。一个 CHAR(10)VARCHAR(10) 字段可能需要最多30个字节才能存储一些UTF8字符。

  3. 除了 utf8_bin 之外的排序规则会更慢,因为排序顺序不能直接映射到字符编码顺序,并且某些存储过程需要进行翻译(因为变量默认为utf8_general_ci排序规则)。

  4. 如果您需要连接UTF8和非UTF8字段,则MySQL将产生严重的性能影响。如果连接的字段具有不同的字符集/排序规则,则原本可以在次内完成的查询可能需要花费几分钟的时间。

底线:

如果您不需要支持非Latin1语言,希望实现最大性能或已经使用 latin1 表格,请选择 latin1

否则,请选择 UTF8


2
语句“您可能需要增加CHAR字段的长度以允许额外的空间,因为VARCHAR(10)只能存储五个或更少字符的UTF8数据。”(在缺点1中)是不正确的。列大小反映允许的最大字符数,而不是存储大小(请参见http://dev.mysql.com/doc/refman/5.6/en/storage-requirements.html)。 - Alessio Gaeta
meden:你说得完全正确。我已经更新了我的答案以反映这个事实。对于错误我表示抱歉。 - Ross Smith II
ASCII怎么样?而不是拉丁文。 - Yousha Aleayoub

20

latin1 是一种单字节编码,因此它可以在相同的存储空间中存储更多字符, MySql 中字符串数据类型的长度取决于编码方式。手册指出:

要计算存储特定 CHAR、VARCHAR 或 TEXT 列值所使用的字节数,必须考虑该列所使用的字符集以及该值是否包含多字节字符。尤其是在使用 utf8 Unicode 字符集时,必须记住不是所有字符都使用相同数量的字节。utf8mb3 和 utf8mb4 字符集可以分别需要每个字符最多三个和四个字节。有关不同类别 utf8mb3 或 utf8mb4 字符所使用的存储的详细信息,请参见第 10.9 节“Unicode 支持”。

此外, 许多字符串操作(例如获取子串和依赖排序规则的比较)在使用单字节编码时更快。

无论如何, 如果您关心国际化, latin1 都不是一个严肃的竞争者。当您将存储已知安全值时(例如百分比编码的 URL),它可能是一个合适的选择。


它是否也支持其他Unicode语言?特别是希伯来语? - qwertymk
它不支持希伯来语,@qwertymk。请参阅http://en.wikipedia.org/wiki/ISO/IEC_8859-1以获取支持的脚本列表,以及确实支持的个别*字符*。 - Michael Petrotta
@qwertymk:显然不是,它被称为西欧字符集。 - Jon
8
如果您从未使用需要多字节的字符,则UTF-8与latin1一样高效。我知道这听起来有些冗余,但它表明,如果您只计划使用英语文本数据,您不会遭受任何存储惩罚,但您可以选择存储任何语言的文本。 - siride
根据http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-utf8.html,MySQL不支持4字节UTF-8。 - Ross Smith II
3
从MySQL版本5.5.3开始,使用utf8mb4字符集时支持中文。尽管如此,我也同意这不是他们最出色的时刻。 - Jon

6

@Ross Smith II,第4点非常重要,意味着列之间的不一致可能很危险。

为了增加已有答案的价值,这里有一个关于字符集差异的小型性能测试:

一个现代的2013服务器,真实使用表格有20000行,在相关列上没有索引。

SELECT 4 FROM subscribers WHERE 1 ORDER BY time_utc_str; (4是缓存破坏器)

  • varchar(20) CHARACTER SET latin1 COLLATION latin1_bin: 15ms
  • varbinary(20): 17ms
  • utf8_bin: 20ms
  • utf8_general_ci: 23ms

对于像数字日期这样的简单字符串,当涉及到性能时,我的决定是使用utf8_bin(CHARACTER SET utf8 COLLATE utf8_bin)。这将防止与其他期望数据库字符集为utf8的代码产生不利影响,同时仍然具有二进制排序的特性。


1

像 latin-1 这样的定长编码在 CPU 消耗方面总是更有效率。

如果某个定长字符集中的令牌集已知足以满足您手头的目的,并且您的目的涉及大量和密集的字符串处理,包括大量的 LENGTH() 和 SUBSTR() 操作,那么这可能是不使用 UTF-8 等编码的一个很好的理由。

哦,顺便说一下。请不要像您所做的那样混淆字符集和其编码。字符集是一些定义的可写字形集。同一字符集可以有多个不同的编码。Unicode 标准的各个版本都构成一个字符集。每个字符集都可以被分别用 UTF-8、UTF-16 和“UTF-32”(不是官方名称,但它指的是为任何字符使用完整的四个字节的想法)编码,后两者都可以采用 HOB-first 或 HOB-last 风格。


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