为何表使用latin1排序规则查询慢,改用utf8mb4后查询速度大幅提升?
性能差异核心原因
这个量级的耗时差本质是关联字段字符集/排序规则不兼容时,数据库无法使用索引完成关联,强制触发全表扫描+逐行字符集转换,带来了数量级的开销差,和utf8mb4本身的存储/计算效率无关。
慢查询阶段的触发逻辑
- 原配置下表A字符集为
latin1、表B为utf8mb3,两个字符集编码规则完全不兼容,做内连接等值比较时,数据库必须对关联字段做隐式字符集转换,才能判断两个值是否相等。 - 数据库优化器无法对「需要做隐式转换的索引字段」使用B+树索引,只能放弃关联字段上的所有索引,选择全表扫描+嵌套循环逐行比较的执行计划。按给出的数据量计算,最坏场景下需要做
25000 * 2000 = 5000万次逐行值转换+比较,1.3秒的耗时完全符合这个计算量级的开销。
改字符集后性能恢复的原因
utf8mb4是utf8mb3的严格超集,同排序规则下编码比较逻辑完全兼容。将表A改为utf8mb4后,只要两张表关联字段的排序规则一致(比如同为utf8mb4_general_ci或utf8mb4_0900_ai_ci),等值比较时不需要做任何隐式转换。- 此时优化器可以正常命中关联字段上的索引,走高效的索引嵌套循环关联逻辑:仅需要扫描2000行的小表B,逐行通过索引去表A做等值匹配,总比较次数仅2000次左右,和之前的5000万次差了4个数量级,0.05秒的耗时是索引生效后的正常表现。
补充说明
- 不要误以为
utf8mb4性能优于latin1:纯英文数字场景下latin1单字符仅占1字节,存储和比较开销理论上比utf8mb4更低,本次性能差完全是字符集不匹配导致的索引失效,和字符集本身的效率无关。 - 注意如果原latin1表中存储了超出latin1编码范围的字符(比如中文、特殊emoji),直接修改字符集可能导致乱码,该问题和本次性能问题无关,需要单独做导出导入修复。
内容的提问来源于stack exchange,提问作者user2280032
相关产品推荐
相关产品推荐

