【问题标题】:utf-8 vs latin1utf-8 与 latin1
【发布时间】:2012-09-16 18:07:03
【问题描述】:

使用 utf8 作为字符集与使用 latin1 相比有哪些优点/缺点?

如果 utf 可以支持更多字符并始终如一地使用,它不是总是更好的选择吗?有什么理由选择latin1吗?

【问题讨论】:

标签: mysql database


【解决方案1】:

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. 如果您需要 JOIN UTF8 和非 UTF8 字段,MySQL 将施加 SEVERE 性能损失。如果加入的字段是不同的字符集/排序规则,那么亚秒级查询可能需要 分钟

底线:

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

否则,请选择UTF8

【讨论】:

  • 声明“您可能需要增加 CHAR 字段的长度以允许额外的空间,因为 VARCHAR(10) 可能只能存储五个或更少字符的 UTF8 数据。 " (在缺点 1 中)是不正确的。列大小反映了允许的最大字符数,而不是存储大小(请参阅dev.mysql.com/doc/refman/5.6/en/storage-requirements.html)。
  • meden:你说得对。我已经更新了我的答案以反映这一事实。抱歉弄错了。
  • ASCII 怎么样?而不是拉丁语
【解决方案2】:

latin1的优点是它是单字节编码,因此它可以在相同的存储空间中存储更多的字符,因为MySql中字符串数据类型的长度取决于编码。手册states那个

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

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

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

【讨论】:

  • 它是否也支持其他 Unicode 语言?尤其是希伯来语?
  • 它不支持希伯来语,@qwertymk。请参阅en.wikipedia.org/wiki/ISO/IEC_8859-1 以获取脚本列表,以及确实支持单个字符
  • @qwertymk:显然not,它被称为西欧字符集。
  • 如果你从不使用需要多个字节的字符,那么 UTF-8 和 latin1 一样高效。我知道这听起来有些多余,但它清楚地表明,如果您只打算使用英文文本数据,您不会受到任何存储损失,但您可以选择存储任何语言的文本。
  • @RossSmithII:从 5.5.3 开始,使用 utf8mb4 字符集。我同意这不是他们最好的时刻之一。
【解决方案3】:

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

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

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

subscribers 中选择 4 个,其中 1 个由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 的其他代码产生任何不利影响,同时仍然是二进制类型。

【讨论】:

    【解决方案4】:

    诸如 latin-1 之类的固定长度编码在 CPU 消耗方面总是更有效。

    如果已知某些固定长度字符集中的标记集足以满足您手头的目的,并且您的目的涉及繁重和密集的字符串处理,其中包含大量 LENGTH() 和 SUBSTR() 内容,那么可能是不使用 UTF-8 等编码的一个很好的理由。

    哦,顺便说一句。不要像您似乎所做的那样混淆字符集与其编码。字符集是一些已定义的可写字形集。同一个字符集可以有多种不同的编码。 unicode 标准的各个版本都构成一个字符集。它们中的每一个都可以进行UTF-8、UTF-16和“UTF-32”(不是官方名称,但它指的是对任何字符使用完整的四个字节的想法)编码,后两者可以分别采用 HOB-first 或 HOB-last 口味。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-15
      • 2014-05-17
      • 2013-09-18
      • 2018-09-24
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 2012-03-24
      相关资源
      最近更新 更多