mysql 中非 utf8 列的建议字符集

Suggested character set for non utf8 columns in mysql

目前,我对 mysql 中的所有字符列使用 VARCHAR/TEXTutf8_general_ci。现在我想改进数据库 layout/performance.

到目前为止我想到的是更好地使用

由于处理问题,我不想将我的 GUID 保存为 BINARY(16),我宁愿将它们保存为 CHAR(32) 以特别改进密钥。 (从 utf8 切换到一些 1 字节字符集时,我什至可以节省 2/3)

在同一个 mysql (innodb) table 中混合使用不同的字符集是一种好习惯吗?或者当所有列在相同的 table 中具有相同的字符集时,我会获得更好的性能吗?甚至数据库?

GUID/UUID/MD5/SHA1 都是十六进制和破折号。对于他们

CHAR(..) CHARACTER SET ascii COLLATE ascii_general_ci

在比较十六进制字符串时,这将允许 A=a

对于 Base64 事物,使用

CHAR(..) CHARACTER SET ascii COLLATE ascii_bin
BINARY(..)

因为 A 在语义上与 a 不同

进一步说明...

  • 如果你给它一个无效的 8 位值,utf8 会吐给你。
  • ascii 向你吐出任何 8 位值。
  • latin1 接受任何东西——因此你以后的问题
  • 在具有不同字符集 and/or 排序规则的 table 中有不同的列是完全可以的。
  • table 上的 charset/collation 只是一个 默认值 ,可以覆盖列定义。
  • BINARY 可能比任何 _bin 排序规则快一点,但还不足以引起注意。
  • 对真正固定长度的列使用CHAR;请勿将其用于其他情况,误导用户。
  • %_bin%_general_ci快,比其他排序规则快。同样,您将很难衡量差异。
  • 切勿使用 TINYTEXTTINYBLOB
  • 为了正确编码,请使用适当的字符集。
  • 对于 "proper sorting",请使用适当的排序规则。请参阅下面的示例。
  • 对于代表多种语言的 "proper sorting",而您使用的是 utf8mb4,请使用 utf8mb4_unicode_520_ci(如果使用 8.0 版,则使用 utf8mb4_900_ci)。 520 和 900 指的是 Unicode 标准;将来可能会出现新的排序规则。

如果您完全使用捷克语,请考虑这些字符集和排序规则。我按首选顺序列出它们:

mysql> show collation like '%czech%';
+------------------+---------+-----+---------+----------+---------+
| Collation        | Charset | Id  | Default | Compiled | Sortlen |
+------------------+---------+-----+---------+----------+---------+
| utf8mb4_czech_ci | utf8mb4 | 234 |         | Yes      |       8 | -- opens up the world
| utf8_czech_ci    | utf8    | 202 |         | Yes      |       8 | -- opens up most of the world
| latin2_czech_cs  | latin2  |   2 |         | Yes      |       4 | -- kinda like latin1

其余为"useless":

| cp1250_czech_cs  | cp1250  |  34 |         | Yes      |       2 |
| ucs2_czech_ci    | ucs2    | 138 |         | Yes      |       8 |
| utf16_czech_ci   | utf16   | 111 |         | Yes      |       8 |
| utf32_czech_ci   | utf32   | 170 |         | Yes      |       8 |
+------------------+---------+-----+---------+----------+---------+
7 rows in set (0.00 sec)

更多

  • 使用较小数据类型(在适当的情况下)的原因是缩小数据集,从而减少 I/O,从而使事物更易于缓存,从而使程序 运行 更快。这对于庞大的数据集尤为重要;它对于中小型数据集不太重要。
  • ENUM 是 1 个字节,但表现得像一个字符串。所以你得到了"best of both worlds"。 (有缺点,ENUM vs TINYINT vs VARCHAR 的拥护者中有 'religious war'。)
  • 通常 "short" 的列的长度始终相同。 country_code 总是 2 个字母,总是 ascii,总是可以受益于不区分大小写的排序规则。所以 CHAR(2) CHARACTER SET ascii COLLATE ascii_general_ci 是最优的。如果你有一些东西有时是 1 个字符,有时是 2 个字符,那么抛硬币;不管你做什么都不会有太大的不同。
  • VARCHAR(最多 255)附加了一个额外的 1 字节长度。因此,如果您的字符串长度 完全不同 VARCHAR 至少与 CHAR 一样好。所以简化你的大脑处理:"variable length --> `VARCHAR".
  • BIT,视版本而定,可以作为 1 字节 TINYINT UNSIGNED 实现。如果您的 table 中只有几位,则不值得担心。
  • 我的一个 Rules of Thumb 说,如果您不太可能获得 10% 的改进,请继续进行其他优化。我们在这里讨论的大部分内容都低于 10%(在本例中为 space)。不过,在写 CREATE TABLE 时养成思考它的习惯。我经常看到带有 BIGINTDOUBLE(每个 8 个字节)的 tables 可以很容易地使用较小的列。有时节省超过 50% (space)。
  • "space"如何转化为"speed"。微小的 tables -> 微小的百分比。巨大的 tables -> 在某些情况下是 10 倍。 (这是 10 倍,而不是 10%。)(UUID 是在巨大 tables 上获得非常糟糕性能的一种方式。)

枚举

  • 行为和感觉像一个字符串,但只占用一个字节。 (一个字节间接转化为轻微的速度提升。)
  • 当少于 10 个不同值时实用。
  • 如果频繁添加新值是不切实际的 -- 需要 ALTER TABLE,但 可以 为 "inplace"。
  • 建议以 'unknown'(或类似的东西)开始列表,并将列设为 NOT NULL(相对于 NULL)。
  • 枚举的字符集必须是用于连接的任何字符集。选择并不重要,除非你有 collat​​e 相等的选项(例如,Aa)。