如果utf8能支持更多字符并且始终如一地使用,它是否总是更好的选择?选择latin1是否有任何原因?
UTF8优点:
支持大多数语言,包括从右到左的语言,如希伯来语。
在与支持UTF8的组件(JavaScript、Java等)导入/导出数据时不需要进行翻译。
UTF8缺点:
非ASCII字符会因其更复杂的编码方式而需要更长时间进行编码和解码。
非ASCII字符可能需要使用多个字节存储(不在ASCII字符集的前127个字符中),因此需要更多的存储空间。一个 CHAR(10)
或 VARCHAR(10)
字段可能需要最多30个字节才能存储一些UTF8字符。
除了 utf8_bin
之外的排序规则会更慢,因为排序顺序不能直接映射到字符编码顺序,并且某些存储过程需要进行翻译(因为变量默认为utf8_general_ci
排序规则)。
如果您需要连接UTF8和非UTF8字段,则MySQL将产生严重的性能影响。如果连接的字段具有不同的字符集/排序规则,则原本可以在次内完成的查询可能需要花费几分钟的时间。
底线:
如果您不需要支持非Latin1语言,希望实现最大性能或已经使用 latin1
表格,请选择 latin1
。
否则,请选择 UTF8
。
CHAR
字段的长度以允许额外的空间,因为VARCHAR(10)
只能存储五个或更少字符的UTF8数据。”(在缺点1中)是不正确的。列大小反映允许的最大字符数,而不是存储大小(请参见http://dev.mysql.com/doc/refman/5.6/en/storage-requirements.html)。 - Alessio Gaetalatin1
是一种单字节编码,因此它可以在相同的存储空间中存储更多字符, MySql 中字符串数据类型的长度取决于编码方式。手册指出:
要计算存储特定 CHAR、VARCHAR 或 TEXT 列值所使用的字节数,必须考虑该列所使用的字符集以及该值是否包含多字节字符。尤其是在使用 utf8 Unicode 字符集时,必须记住不是所有字符都使用相同数量的字节。utf8mb3 和 utf8mb4 字符集可以分别需要每个字符最多三个和四个字节。有关不同类别 utf8mb3 或 utf8mb4 字符所使用的存储的详细信息,请参见第 10.9 节“Unicode 支持”。
此外, 许多字符串操作(例如获取子串和依赖排序规则的比较)在使用单字节编码时更快。
无论如何, 如果您关心国际化, latin1 都不是一个严肃的竞争者。当您将存储已知安全值时(例如百分比编码的 URL),它可能是一个合适的选择。
utf8mb4
字符集时支持中文。尽管如此,我也同意这不是他们最出色的时刻。 - Jon@Ross Smith II,第4点非常重要,意味着列之间的不一致可能很危险。
为了增加已有答案的价值,这里有一个关于字符集差异的小型性能测试:
一个现代的2013服务器,真实使用表格有20000行,在相关列上没有索引。
SELECT 4 FROM subscribers
WHERE 1 ORDER BY time_utc_str
; (4是缓存破坏器)
对于像数字日期这样的简单字符串,当涉及到性能时,我的决定是使用utf8_bin(CHARACTER SET utf8 COLLATE utf8_bin)。这将防止与其他期望数据库字符集为utf8的代码产生不利影响,同时仍然具有二进制排序的特性。
像 latin-1 这样的定长编码在 CPU 消耗方面总是更有效率。
如果某个定长字符集中的令牌集已知足以满足您手头的目的,并且您的目的涉及大量和密集的字符串处理,包括大量的 LENGTH() 和 SUBSTR() 操作,那么这可能是不使用 UTF-8 等编码的一个很好的理由。
哦,顺便说一下。请不要像您所做的那样混淆字符集和其编码。字符集是一些定义的可写字形集。同一字符集可以有多个不同的编码。Unicode 标准的各个版本都构成一个字符集。每个字符集都可以被分别用 UTF-8、UTF-16 和“UTF-32”(不是官方名称,但它指的是为任何字符使用完整的四个字节的想法)编码,后两者都可以采用 HOB-first 或 HOB-last 风格。
utf8mb4
而非utf8
- 这是 MySQL 的一种错误。 - xmedeko