MySQL优化问题:关联查询未使用预期主键
嘿,这个问题我之前帮不少开发者排查过,核心大概率就是你刚发现的字符集不匹配在搞鬼!咱们一步步拆解:
为什么会出现全表扫描、行数异常?
当两个关联表的字符集(或排序规则)不一致时,数据库在执行关联查询或条件匹配时,会触发隐式字符集转换——简单说就是数据库得把其中一个表的字段编码转换成另一个表的编码才能做比较。这个转换操作会直接让主键索引失效,因为索引是基于原字符集编码构建的,转换后索引就用不上了,只能被迫全表扫描sold_data这个大表。
而且字符集不匹配还会导致字符串比较逻辑混乱:比如不同字符集下,看起来相同的mls_id='FL-REG'可能被判定为不同值,或者转换后匹配范围被扩大,这就是你查到的行数比实际多的原因,自然查询耗时会暴涨。
怎么验证和解决?
1. 先确认字符集差异
先跑这两条SQL,确认两个表的字符集和排序规则是否真的不一致:
SHOW CREATE TABLE sold_data; SHOW CREATE TABLE [你的另一个关联表名];
重点看输出里的CHARSET和COLLATE字段,只要这两个有一个不一样,就是问题根源。
2. 统一字符集(关键步骤)
把两个表的字符集和排序规则调整为一致,推荐用utf8mb4(支持所有Unicode字符,兼容性最好):
-- 调整sold_data表字符集 ALTER TABLE sold_data CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 调整另一个关联表字符集 ALTER TABLE [关联表名] CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
⚠️ 注意:大表执行这个操作会锁表,一定要在业务低峰期操作,操作前记得备份数据!
3. 验证查询是否恢复正常
字符集统一后,用EXPLAIN查看你的查询执行计划:
EXPLAIN [你的查询语句];
你应该能看到查询开始使用主键索引,扫描行数也会和mls_id='FL-REG'的实际行数匹配,耗时会大幅下降。
4. 额外检查(如果还有问题)
如果字符集统一后还是有问题,排查下查询语句里有没有其他导致索引失效的写法:比如在mls_id字段上用了函数、做了隐式类型转换(现在字符集统一了就不会有这个问题了),确保查询条件是直接的mls_id='FL-REG'形式。
内容的提问来源于stack exchange,提问作者Andy Wallace

