【问题标题】:Does joining ASCII and UTF-8 tables add overhead?加入 ASCII 和 UTF-8 表会增加开销吗?
【发布时间】:2019-04-06 23:51:42
【问题描述】:

使用CHARACTER SET ascii COLLATE ascii_bin 会稍微快一些,很多表都可以正常工作。这是一个例子:

CREATE TABLE `session` (
    `id` CHAR(64) NOT NULL,
    `created_at` INTEGER NOT NULL,
    `modified_at` INTEGER NOT NULL,
    PRIMARY KEY (`id`),
    CONSTRAINT FOREIGN KEY (`user_id`) REFERENCES `user`(`id`)
) CHARACTER SET ascii COLLATE ascii_bin;

但如果我要加入:

CREATE TABLE `session_value` (
    `session_id` CHAR(64) NOT NULL,
    `key` VARCHAR(64) NOT NULL,
    `value` TEXT,
    PRIMARY KEY (`session_id`, `key`),
    CONSTRAINT FOREIGN KEY (`session_id`) REFERENCES `session`(`id`) ON DELETE CASCADE
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

会发生什么?逻辑告诉我它应该是无缝的,因为 ASCII 是 UTF-8 的子集。人性告诉我,从核心转储到屏幕上出现的消息Follow the white rabbit.,我可以期待任何事情。 ¯\_(ツ)_/¯

【问题讨论】:

  • same 表中的不同列可以不同CHARACTER SET 和/或COLLATION。每当您在两个不同的表中具有“相同”值时,使这些列 same;不要依赖“子集”规则。

标签: mysql utf-8 character-encoding ascii query-performance


【解决方案1】:

连接 ASCII 和 UTF-8 表会增加开销吗?

是的

如果你这样做了

SELECT whatever 
  FROM session s
  JOIN session_value v 
         ON s.id = v.session_id

查询引擎必须比较idsession_id 的许多值才能满足您的查询。

如果idsession_id 具有完全相同的数据类型,查询规划器将能够利用索引和快速比较。

但如果它们有不同的字符集,查询规划器必须按如下方式解释您的查询。

 ...  JOIN session_value v 
         ON CONVERT(s.id USING utf8mb4) = v.session_id

当 WHERE 或 ON 条件的形式为 f(column) 时,它会使查询不可分割:它会阻止有效的索引使用。这会影响查询性能。

在您的情况下,当您将行插入session_value 时会出现类似的性能问题:服务器必须进行转换以检查您的外键约束。

如果这些表要投入生产,您最好为这些列使用相同的字符集。拥有数千行比拥有数百万行更容易解决此问题。认真的。

What makes a SQL statement sargable?

【讨论】:

    【解决方案2】:

    为什么不一直使用 UTF-8?拥有 ASCII 表通常是一个错误,这表明您忘记在某些东西上设置编码。使用单一编码可以极大地简化您的内部架构。

    仅当您有 CHARVARCHARTEXT 列时,编码才相关。

    如果您有该类型的列,则值得将其默认设置为 UTF8MB4

    【讨论】:

    • 它确实有一个 char 列
    • 然后将其设为 UTF-8,它将避免可能减慢查询速度的转换步骤。我不确定它是否是一个干净的子集。
    猜你喜欢
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多