mysql sql语句执行时是否使用索引检查方法
在日常开发中,使用到的数据表经常都会有索引,这些索引可能是开发人员/DBA建表时创建的,也可能是在使用过程中新增的。合理的使用索引,可以加快数据库查询速度。然而,在实际开发工作中,会出现有些sql语句执行时不会使用索引、而使用了全表扫描的情况,造成执行速度慢的问题。下面我列举两种比较典型的场景:
场景一:mysql时间字段上使用like
表结构:
CREATE TABLE `orders` (
`orders_id` int(11) NOT NULL,
`order_status` tinyint(4) NOT NULL,
`date_purchased` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`orders_id`),
KEY `idx_date_purchased` (`date_purchased`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
原始语句:
注意到此sql只返回一条结果集,但是有like,把时间字段当成字符串处理了,就做了隐式转换,故没法走索引,而是走了全表扫描。
修改后的sql:
场景二:字段本身是字符类型,但是where 条件后却用整形(没有加引号)。
为了避免上述问题,除了日常开发中多加小心外,还可以通过explain来检查sql是否使用索引。方法如下:
(1) 登录Linux服务器mysql环境(注意不要使用windows本机环境的mysql进行测试,因为测试发现windows mysql下explain检查结果和linux mysql有不一致的情况)
(2) 将mybatis resource文件中的sql语句中的变量填写成具体值,并在sql语句前加explain执行,如下:
explain执行结果关注以下几个字段:
type:
显示sql执行的类型,从最好到最差的类型为system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL。一般来说,type至少要达到range级别,最好达到ref级别,低于range级别的sql必须进行优化。
key:
显示sql执行过程中实际使用的键或索引,如果为null则表示未使用任何索引,必须进行优化。
Extra:
如果是Only index,这意味着信息只用索引树中的信息检索出的,这比扫描整个表要快。
如果是where used,就是使用上了where限制。
如果是impossible where 表示用不着where,一般就是没查出来啥。
如果此信息显示Using filesort或者Using temporary的话会很吃力,WHERE和ORDER BY的索引经常无法兼顾,如果按照WHERE来确定索引,那么在ORDER BY时,就必然会引起Using filesort,这就要看是先过滤再排序划算,还是先排序再过滤划算。