暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

mysql删除索引可能是为了优化SQL

MySQLDBA运维零基础自学 2021-04-13
1186

你可能会感觉很奇怪,索引不是优化SQL用的吗?为什么优化SQL要删掉索引,别急,先看这个实验。


创建一个表

    CREATE TABLE `t`(  
    `id` int(11NOT NULL
     `a` int(11) DEFAULT NULL,  
     `b` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `a` (`a`),
      KEY `b` (`b`)) ENGINE=InnoDB


    插入10w行数据

      delimiter // 
      create procedure idata()
      begin declare i int;
      set i=1;
      while(i<=100000)do
      insert into t values(i, i, i);
      set i=i+1;
      end while;
      end//
      delimiter ;


      首先我们来看,该查询使用了range扫描方式,也就是使用了索引a的范围扫描,这个很容易理解到,mysql的优化器选择了a索引


      再来看这条

         explain select * from t where (a between 1 and 1000) and
        (b between 50000 and 100000) order by b limit 1;

        那么优化器该怎么选择索引呢?


        如果使用索引 a 进行查询,那么就是扫描索引 a 的前 1000 个值,然后取到对应的 id,再到主键索引上去查出每一行,然后根据字段 b 来过滤。显然这样需要扫描 1000 行。


        如果使用索引 b 进行查询,那么就是扫描索引 b 的最后 50001 个值,与上面的执行过程相同,也是需要回到主键索引上取值再判断,所以需要扫描 50001 行。


        你一定会想,如果使用索引 a 的话,执行速度明显会快很多。那么,下面我们就来看看到底是不是这么一回事儿。


        结果却不尽人意,优化器选错了索引,选择了索引 b 而 rows 字段显示需要扫描的行数是 50155。(这里需要解释下,扫描行数的值是采样估算的,所以一般不是精准的)


        很明显,优化器选错了索引,那我们如何修正呢

        (1)可以采用force index强制使用索引a

        可以看到,这次扫描的数据只有1000行了。

        (2)为什么优化器选择了b?

        之前优化器选择使用索引 b,是因为它认为使用索引 b 可以避免排序(b 本身是索引,已经是有序的了,如果选择索引 b 的话,不需要再做排序,只需要遍历),所以即使扫描行数多,也判定为代价更小。

        这样的sql,也正确选择了索引

        (3)删除索引b

        对于生产环境中,可以结合业务分析,如果该索引没有有利于业务,还不如删掉它。


        其实这也是mysql优化器的一个bug,索引的选择,是优化器的工作,之前我也遇到过很多优化器的坑。


        优化器选择索引的目的,是找到一个最优的执行方案,并用最小的代价去执行语句。在数据库里面,扫描行数是影响执行代价的因素之一。扫描的行数越少,意味着访问磁盘数据的次数越少,消耗的 CPU 资源越少。当然,扫描行数并不是唯一的判断标准,优化器还会结合是否使用临时表、是否排序等因素进行综合判断。

        在这里,我们优化器就是错误判断了排序因素。


        在解决今天遇到这句SQL上,最加选择是第3种方法,因为第一种方法,程序员并不知道项目到了线上后的结果,一般都是出bug了才会修改,并且这种语法并不适合将来万一迁移数据库。第二种方法,并没有结合实际,只是主观的修复bug而拼写,不实用。因此,遇到这种情况,最佳选择,结合实际,和开发协商,删除掉“不好用”的索引。


        今天的内容就到这里了,另外请大家帮个小忙,帮忙扫描下图,投个票。谢谢大家,哈哈。


        最后修改时间:2021-04-14 09:14:23
        文章转载自MySQLDBA运维零基础自学,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论