MySQL 慢查询 —— 值类型与字段类型不一致的隐式转换
示例慢 SQL
SELECT * FROM task_engine_base_data WHERE outer_task_id = 1001871
场景上下文
- 数据表结构现状
为减少阅读干扰,已去除与本案例无关的字段及索引定义
CREATE TABLE `task_engine_base_data` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`task_type_id` int(11) NOT NULL DEFAULT '0' COMMENT '任务类型ID',
`outer_task_id` varchar(64) NOT NULL DEFAULT '' COMMENT '外部任务ID',
PRIMARY KEY (`id`),
KEY `idx_outer_id_type_id` (`outer_task_id`,`task_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='子任务规则表';
原因分析
慢SQL的EXPLAIN
文章图片
表中存在索引
idx_outer_id_type_id(outer_task_id,task_type_id)
。字段定义
outer_task_id varchar(64) NOT NULL DEFAULT ''
。字段类型为字符串,但查询条件的值为整型,导致 MySQL 隐式转换。
列值会被转换成浮点数类型,即
CAST(col_name AS DOUBLE) = XXX
,对列值进行了计算,无法使用索引。解决方案 程序中强制转换值的类型,与数据库字段类型保持完全一致,避免隐式转换。
SELECT * FROM task_engine_base_data WHERE outer_task_id = '1001871'
或者使用
CAST
转换查询值:SELECT * FROM task_engine_base_data WHERE outer_task_id=CAST(1001871 AS CHAR)
优化后的 SQL
SELECT * FROM task_engine_base_data WHERE outer_task_id = '1001871'
再看优化后的EXPLAIN
文章图片
知识总结 两个需要比较的值,基本类型不一样时,会发生转换。
整型与字符串的比较,两个值都会被转换成浮点数后再比较。
【MySQL 慢查询 —— 值类型与字段类型不一致的隐式转换】对索引列进行计算,会导致无法使用索引。
参考资料
- 《MySQL 5.7 Reference Manual》Type Conversion in Expression Evaluation
感谢您的阅读,觉得内容不错,点个赞吧
原文地址: https://shockerli.net/post/mysql-slow-sql-implicit-type-conversion/
推荐阅读
- 慢慢的美丽
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- mybatisplus如何在xml的连表查询中使用queryWrapper
- mybatisplus|mybatisplus where QueryWrapper加括号嵌套查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- 2020-10-18|2020-10-18 致各位慢友
- 慢煮岁月,浅思淡行
- 慢就是快
- py连接mysql
- 2019-01-18Mysql中主机名的问题