从这期开始我会分享几期MySQL 的SQL语句优化的几个案例。

一、SQL语句及执行时间如下

select * from data_test where a=1811190042013;

二、表结构

CREATE TABLE `data_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` varchar(20) DEFAULT NULL,
`b` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_a` (`a`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1570204 DEFAULT CHARSET=utf8;

三、索引详情

注:Cardinality表示索引中唯一值的数目

四、分析

表data_test中a字段有索引,但是查询时间为什么也需要这么久?

首先看执行计划(可以通过Navicat等工具点击“解释”或者在SQL前面加explain查看执行计划)

走不了a字段索引的原因:a字段类型是varchar(20),而输出的参数却是整型。(条件a=1811190042013这个值没加单引号,MySQL认为是整型)

在MySQL中,字符串和数字做比较的话,是将字符串转换成数字再进行比较

也就是SQL相当于

select * from data_test where CAST(a AS signed int)=1811190042013;

由于MySQL对索引字段做函数操作,优化器会放弃走索引(原因是对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器放弃走树索引功能)

五、SQL优化结果

由第三步可知,是因为MySQL发生了隐式转换,导致a字段的查询走不了索引,因此,需要避免隐式转换的情况,改写的SQL如下:

select * from data_test where a=’1811190042013‘;

优化后执行时间

优化后执行计划

加上单引号有效果明显,因此如果碰到有索引的字符串类型字段做条件查询时,记得加上单引号防止隐式转换哦。

参考:林晓斌的“MySQL实战45讲”