utf-8 vs latin1

qwe*_*ymk 16 mysql database

使用utf8作为charset与使用latin1之间有什么优点/缺点?

如果utf可以支持更多的字符并且一直使用它不会永远是更好的选择吗?有没有理由选择拉丁1?

Ros*_* II 18

UTF8优点:

  1. 支持大多数语言,包括希伯来语等RTL语言.

  2. 将数据导入/导出到UTF8感知组件(JavaScript,Java等)时无需转换.

UTF8缺点:

  1. 由于编码方案更复杂,非ASCII字符将花费更多时间进行编码和解码.

  2. 非ASCII字符将占用更多空间,因为它们可能使用超过1个字节存储(字符不在ASCII字符集的前127个字符中).一个CHAR(10)或多个VARCHAR(10)字段可能需要最多30个字节来存储一些UTF8字符.

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

  4. 如果您需要JOINUTF8和非UTF8字段,MySQL将会产生严重的性能损失.如果加入的字段是不同的字符集/排序规则,那么亚秒级查询可能需要几分钟.

底线:

如果您不需要支持非Latin1语言,想要获得最大性能,或者已经有表使用latin1,请选择latin1.

否则,选择UTF8.

  • 声明“您可能需要增加 `CHAR` 字段的长度以留出额外空间,因为 `VARCHAR(10)` 可能只能存储 5 个或更少字符的 UTF8 数据。” (在缺点1)是不正确的。列大小反映了允许的最大字符数,而不是存储大小(请参阅 http://dev.mysql.com/doc/refman/5.6/en/storage-requirements.html)。 (2认同)

Jon*_*Jon 12

latin1它具有单字节编码的优点,因此它可以在相同数量的存储空间中存储更多字符,因为MySql中字符串数据类型的长度取决于编码.手册说明了这一点

要计算用于存储特定CHAR,VARCHAR或TEXT列值的字节数,必须考虑用于该列的字符集以及该值是否包含多字节字符.特别是,在使用utf8(或utf8mb4)Unicode字符集时,必须记住,并非所有字符都使用相同的字节数,并且每个字符最多可能需要三(4)个字节.有关用于不同类别的utf8或utf8mb4字符的存储的细分,请参见第10.1.10节"Unicode支持".

此外,对于单字节编码,许多字符串操作(例如,采用子字符串和与校对相关的比较)更快.

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

  • 如果您从不使用需要多个字节的字符,那么UTF-8与latin1一样高效.我知道这听起来多余,但它清楚地表明,如果您只打算使用英文文本数据,则不会产生任何存储损失,但您可以选择存储来自任何语言的文本. (5认同)
  • @RossSmithII:从 5.5.3 开始,使用 [`utf8mb4`](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html) 字符集。我同意这不是他们最好的时刻之一。 (3认同)

Joh*_*han 5

@Ross Smith II,第 4 点很有价值,这意味着列之间的不一致可能很危险。

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

现代 2013 服务器,实际使用的表有 20000 行,相关列上没有索引。

subscribersWHERE 1 ORDER BY 中选择 4 time_utc_str;(4 是缓存破坏者)

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

对于像数字日期这样的简单字符串,当考虑到性能时,我的决定是使用 utf8_bin (CHARACTER SET utf8 COLLATE utf8_bin)。这将防止对其他期望数据库字符集为 utf8 而仍然是二进制类型的代码产生任何不利影响。