Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > mysql不走索引

mysql不走索引的几个问题小结

作者:风破冬

MySQL中不走索引的问题通常发生在查询中使用了函数,这会使索引失效,从而影响查询性能,本文就介绍了mysql不走索引的几个问题小结,感兴趣的可以了解一下

一、类型不匹配导致不走索引

这类问题往往是因为数据定义与使用上面的偏差,比如工号,定义成varchar,然而用的时候又不讲工号打上引号

创建表代码举例如下:

----创建表:
CREATE TABLE `test_a`(
    `id` int(11) NOT NULL,
    `work_no` varchar(11) DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `index_work_no`(`work_no`)
)ENGINE=InnoDB;

查询条件对比如下:

----查询工号,执行一下-----
explain SELECT * from test_a where work_no=1000;
explain  SELECT * from test_a where work_no="1000";

结论,可以自己运行一下代码,会发现上面的因为定义成了varchar,但是用的时候又在把它当int用,没有加引号,导致无法走索引

二、索引用错的问题

这个是索引用错的问题,创建表及初始化数据代码如下:

----创建表:
CREATE TABLE `test_t`(
    `id` int(11) NOT NULL,
    `a` int(11) DEFAULT NULL,
    `b` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `index_a`(`a`),
    KEY`index_b`(`b`)
)ENGINE=InnoDB;
-----定义初始化10w数据函数:
delimiter;;
create procedure idata()
begin
    declare i int;
    set i=1;
    while(i<=100000) do
    insert into test_t values(i,i,i);
    set i=i+1;
    end while;
end;;
delimiter;
call idata();
----删除存储过程
drop procedure idata;

相关查询对比:

----查询条件
explain select * from test_t where (a BETWEEN 1 and 1000) and (b BETWEEN 50000 and 100000) order by b limit 1;
explain select * from test_t force index(index_a) where (a BETWEEN 1 and 1000) and (b BETWEEN 50000 and 100000) order by b limit 1;

结论,最终出现第一个走错了索引,导致查询时候会变长的问题。

而下面的我们加强制走索引,会发现执行扫描行数要少很多,主要原因还是发生在order上

如果做下面的修改不强制走索引也能够走正确的索引就是order by b, a。同时放上去也是有效的

三、条件字段为函数的操作导致不走索引

函数作用在索引字段上导致不走索引,其实感觉mysql尽量少用函数,虽然提供了,往往还是占用的mysql自己的资源做的计算。mysql数据库的资源多贵呀,物理机多便宜呀

----创建表:
CREATE TABLE `trade_log`(
    `id` int(11) NOT NULL,
    `created_time` datetime NOT NULL DEFAULT,
    `b` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `index_created_time`(`created_time`)
)ENGINE=InnoDB;
-----定义初始化10w数据函数:
delimiter;;
create procedure c_trade_log()
begin
    declare i int;
    set i=1;
    while(i<=100000) do
    insert into trade_log values(i,from_unixtime(1539123415 + 1000*i),i);
    set i=i+1;
    end while;
end;;
delimiter;
call c_trade_log();
----删除存储过程
DROP PROCEDURE c_trade_log

查询条件:

explain SELECT count(*) from trade_log where month(created_time)=7;
SELECT count(*) from trade_log where month(created_time)=7;
-----优化-----
explain SELECT count(*) from trade_log where created_time BETWEEN "2018-07-01" and "2018-08-01"
or created_time BETWEEN "2019-07-01" and "2019-08-01"
or created_time BETWEEN "2020-07-01" and "2020-08-01"
or created_time BETWEEN "2021-07-01" and "2021-08-01" ;

四、错误计算不走索引

查询条件:继续沿用上面的trade_log表

索引字段做减法在等号前,与等号后的区别

--不走索引
explain SELECT * from trade_log where id -1000=3030300
--走索引
explain SELECT * from trade_log where id =3030300-1000
 

五、in后面的公式

继续使用test_t表

--不走索引 因为有max,不要究竟这儿为什么要加max公式,主要是为了突出这儿不走索引给的一个例子
explain select * FROM test_t WHERE id IN
( SELECT max(id) FROM test_t WHERE a BETWEEN 1000 and 2000 GROUP BY a )
--走索引
explain select * FROM test_t WHERE id IN
( SELECT id FROM test_t WHERE a BETWEEN 1000 and 2000 GROUP BY a )

不走索引的结果:

走索引的结果: 

其他:慢sql相关配置开启命令

----慢查询开启情况---
show variables like "slow_query_log";
----设置开启----
set global slow_query_log = "ON";
---慢查询日志地址---
show variables like "slow_query_log_file";

到此这篇关于mysql不走索引的几个问题小结的文章就介绍到这了,更多相关mysql不走索引内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文