1背景
昨天晚上某群友问我一个SQL优化问题,我当时在处理公司问题,就让他丢到群里大家看。经过大家“我来找茬”,最终问题得以解决。废话到这里,上菜。
2问题SQL
代码语言:javascript复制SELECT *
FROM table1 t1
WHERE t1.number IN (
SELECT batch_no
FROM table2
WHERE id = '260002'
);
表结构 t1
代码语言:javascript复制CREATE TABLE `table1` (
`id` varchar(38) NOT NULL COMMENT 'id',
`number` varchar(50) NOT NULL COMMENT '调整后交易批号',
PRIMARY KEY (`id`),
KEY `idx1` (`number`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='交易单明细';
表结构 t2
代码语言:javascript复制CREATE TABLE `table2` (
`id` varchar(38) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id',
`batch_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '结算批号',
PRIMARY KEY (`id`),
KEY `idx1` (`batch_no`),
) ENGINE = InnoDB CHARSET = utf8mb3 COMMENT '结算单';
3现象
针对问题SQL,加force index, 各种改写,都没法走索引,表数据大概有300w,所以还是有点影响。
4结论
表字段和表的字符集不一致,查询的时候发生了隐式转换。表字段用了utf8mb4,表默认定义用utf8mb3,混合使用。导致batch_no是utf8mb4, number字段是utf8mb3。
5解决方案
1、修改字符集 2、改写SQL select convert(batch_no using utf8) from ....
我个人觉得这个问题的根本原因还是SQL在上线的时候没有做好审核,缺乏SQL审核工具与开发规范约束。