我有下表:
CREATE TABLE `tokens` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`s_id` int(10) unsigned NOT NULL,
`a_token` char(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`a_token_exp` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u_a_token` (`a_token`) USING HASH,
KEY `f_seid` (`s_id`),
CONSTRAINT `f_seid` FOREIGN KEY (`s_id`) REFERENCES `sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
我想更改字符集,a_token
因为我们使用以下命令仅使用 ascii 字符:
ALTER TABLE tokens MODIFY a_token CHAR(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL;
Run Code Online (Sandbox Code Playgroud)
和新SHOW CREATE TABLE
节目:
CREATE TABLE `tokens` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id` int(10) unsigned NOT NULL,
`a_token` char(40) CHARACTER SET ascii NOT NULL,
`a_token_exp` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u_a_token` (`a_token`) USING HASH,
KEY `f_seid` (`s_id`),
CONSTRAINT `f_seid` FOREIGN KEY (`s_id`) REFERENCES `sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
然后我跑OPTIMIZE TABLE oauth_session_access_tokens
。
这个查询应该(我不确定)我的模式表的大小:
SELECT table_name AS "Table",
((data_length + index_length)) AS "Size"
FROM information_schema.TABLES
WHERE table_schema = "test"
ORDER BY (data_length + index_length) DESC;
Run Code Online (Sandbox Code Playgroud)
但具体的表tokens
总是返回49152前后ALTER TABLE
。
我可以假设即使使用 CHAR 和 utf8,如果只有 ASCII 字符,那么该字段也不会为 utf8 预分配空间吗?
UTF-8 是一种变长字符编码。对于 ASCII 范围内的字符,每个字符只需要 1 个字节。对于需要它的字符,每个字符仅使用 2、3 或 4 个字节。
关于 UTF-8 的维基百科文章有一个很好的解释和多字节编码如何工作的说明。https://en.wikipedia.org/wiki/UTF-8
因此,即使您只有 ASCII 字符要存储,使用 UTF-8 也没有什么缺点。