我的php web应用程序中的所有mysql表都是使用utf8编码的myisam。因为记录可以在脱机时从一个伴随应用程序生成,所以我的表键是随机生成的,字母数字varchars;这些字段通过utf8\u bin编码设置为二进制,因此它们可以区分大小写。
我最近决定更改所有文本字段的编码,以支持一些用户喜欢输入的emojis。我接着把所有的utf8字段都改成了utf8mb4,包括键。我立即开始看到性能问题,其中一个较大表上的复杂select查询花费了一分钟以上,然后其他查询排队等待表锁。我将表上主键字段的编码改回utf8,性能恢复正常。几天后,我再次将该字段更改为utf8mb4,查询再次开始排队,并将其更改为恢复正常性能。
因此,运行平稳:
`ID` varchar(8) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT ''
但这会带来问题:
`ID` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT ''
我读到的所有东西都说utf8和utf8mb4应该有相同的性能,但我看到我的情况有明显的不同。这有道理吗?
将关键字段保留在utf8并不是什么问题,因为我预计在那里使用的不仅仅是简单的字母数字字符。但我希望将所有字段设置为相同的编码,只是为了保持一致性和维护的简单性(不必记住将用户填充的字段设置为一种编码,将关键字段设置为另一种编码)。
关于@mandyshaw的评论
当我使用sequel pro mac应用程序处理数据库时,控制台会不断显示成对的 SET NAMES 'utf8'
以及 SET NAMES 'utf8mb4'
条目,所以这并不意味着所有设置都是正确的。不过,我目前的情况是:
MySQL [(none)]> SHOW GLOBAL VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
我读到了 character_set_system
无法从utf8和 character_set_filesystem
应该是二进制的。
sequel pro的连接编码设置为autodetect,但是当我显式地将其更改为utf8mb4,然后打开一个新的连接时,我仍然可以在控制台中看到所有这些编码更改。
还有什么我需要改变的使用这种编码一致?
1条答案
按热度按时间whitzsjs1#
utf实际上是utfmb3,每个字符最多使用3个字节,而utfmb4每个字符最多使用4个字节。对于varchar列,这通常不会有太大的区别,因为mysql只存储所需的字节数(除非您使用row\u format=fixed创建了myisam表)。
但是,在查询执行期间,mysql可能会在内存存储引擎中创建临时表,该引擎不支持可变长度行。这些临时表有一个最大大小,如果超过这个大小,临时表将转换为myisam/innodb中的表(取决于您的mysql版本)。状态变量
Created_tmp_disk_tables
每次发生这种情况时都将递增。如果是这样,试着看看它是否有助于增加max_heap_table_size
和tmp_table_size
.或者,升级到MySQL8.0,其中新的支持可变长度行的存储引擎用于内部临时表。