latin1 是否比 utf8 有性能优势?

Ale*_*xey 9 mysql mysql-5.7

我有一个utf8包含 > 80M 记录的表,其中一列 ( char(6) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL) 可以只包含拉丁符号 ( [a-zA-Z0-9])。将此列转换为latin1是否有意义?

MySQL文档说:

要使用 UTF-8 节省空间,请使用 VARCHAR 而不是 CHAR。否则,MySQL 必须为 CHAR CHARACTER SET utf8 列中的每个字符保留三个字节,因为这是最大可能的字符长度。例如,MySQL 必须为 CHAR(10) CHARACTER SET utf8 列保留 30 个字节。

我做了一个测试 - 创建了 2 个具有相同 50M 记录的表:

CREATE TABLE `t_utf8` (
  `c_1` char(6) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  UNIQUE KEY `index_t_utf8_on_c_1` (`c_1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

CREATE TABLE `t_lat` (
  `c_1` char(6) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  UNIQUE KEY `index_t_lat_on_c_1` (`c_1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
Run Code Online (Sandbox Code Playgroud)

但是 MySQL 说它们的大小几乎相同:

           Name: t_lat
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 57557700
 Avg_row_length: 30
    Data_length: 1741668352
Max_data_length: 0
   Index_length: 0
      Data_free: 2097152
 Auto_increment: NULL
      Collation: utf8_general_ci
 Create_options: row_format=COMPACT

           Name: t_utf8
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 57554528
 Avg_row_length: 31
    Data_length: 1810874368
Max_data_length: 0
   Index_length: 0
      Data_free: 3145728
 Auto_increment: NULL
      Collation: utf8_general_ci
 Create_options: row_format=COMPACT
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

  • MySQL 5.7
  • 数据库

PS:我用 MyISAM 做了同样的测试并得到了预期的好处:latin1 - 383Mb,utf8 - 1Gb 的表。但是为什么它不适用于 InnoDB?

Ric*_*mes 5

简短的回答:别打扰。

长答案:

  • https://bugs.mysql.com/bug.php?id=84440——你可能会也可能不会节省空间。
  • InnoDB 本质上比 MyISAM 大。
  • 在 utf8 中比较字符比在 latin1 中稍慢。但你可能不会注意到。
  • 1741668352 abd 1810874368 之间的微小差异可能是由于您如何从另一个表构建一个表的随机性。或者月相,没什么重要的。
  • 30 对 31 来自 InnoDB 估计事物的方式。

CHAR除了真正固定长度的字符串之外,不要使用。它们几乎总是 ascii,例如 country_code、postal_code、UUID、hex、md5 等。

创建列/表时养成明确说出 ascii 或 utf8mb4 的习惯,除非您有需要其他内容的异常情况。