使用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.
,我可以期待任何事情。 ¯\ _(ツ)_ /¯
答案 0 :(得分:1)
联接ASCII和UTF-8表会增加开销吗?
是。
如果您这样做
SELECT whatever
FROM session s
JOIN session_value v
ON s.id = v.session_id
查询引擎必须比较id
和session_id
的许多值才能满足您的查询。
如果id
和session_id
具有完全相同的数据类型,则查询计划者将能够利用索引和快速比较。
但是,如果它们具有不同的字符集,则查询计划者必须按以下方式解释您的查询。
... JOIN session_value v
ON CONVERT(s.id USING utf8mb4) = v.session_id
当WHERE或ON条件的格式为f(column)
时,它将使查询不可查询:它将阻止有效使用索引。这会影响查询性能。
在您的情况下,当您向session_value
插入行时,也会发生类似的性能问题:服务器必须进行转换以检查您的外键约束。
如果这些表要投入生产,那么对这些列使用相同的字符集将是非常明智的。拥有数千行时,修复此问题要比拥有数百万行时修复起来容易得多。认真地。
答案 1 :(得分:0)
为什么不一直使用UTF-8?使用ASCII表通常是一个错误,这是您忘记为某些内容设置编码的标志。使用单一编码可以大大简化您的内部架构。
仅当具有CHAR
,VARCHAR
或TEXT
列时,编码才有意义。
如果您有该类型的列,则值得将其默认设置为UTF8MB4
。