首页 > 文章列表 > 1.5万字+30张图盘点索引常见的11个知识点

1.5万字+30张图盘点索引常见的11个知识点

mysql
141 2023-05-24

大家好,我是三友~~

今天来盘点一下关于MySQL索引常见的知识点

本来这篇文章我前两个星期就打算写了,提纲都列好了,但是后面我去追《漫长的季节》这部剧去了,这就花了一个周末的时间,再加上后面一些其它的事,导致没来得及写

不过不要紧,好饭不怕晚,虽迟但到,走起,开干!

图片

对了,本文主要是针对InnoDB存储引擎进行讲解。

索引分类

索引的分类可以从不同的维度进行分类

1、按使用的数据结构划分
B+树索引Hash索引...
2、按实际的物理存储数据构划分
聚簇索引非聚簇索引(二级索引)

聚簇索引和非聚簇索引后面会着重说。

3、按索引特性划分
主键索引唯一索引普通索引全文索引...
4、按字段个数划分
单列索引联合索引

索引数据结构

准备

为了接下来文章更好地讲解,这里我准备了一张user表,接下来整篇文章的示例会以这张表来讲解

之所以这个优化叫索引下推,其实是跟判断age > 22逻辑执行的地方有关,这里就不过多赘述了。索引合并索引合并(index merge)是从MySQL5.1开始引入的索引优化机制,在之前的MySQL版本中,一条sql多个查询条件只能使用一个索引,但是引入了索引合并机制之后,MySQL在某些特殊的情况下会扫描多个索引,然后将扫描结果进行合并结果合并会为下面三种情况:取交集(intersect)取并集(union)排序后取并集(sort-union)为了不耽误演示,删除之前所有的索引,然后为name和age各自分别创建一个二级索引idx_name和idx_age取交集(intersect)当执行下面这条sql就会出现取交集的情况mysql对上述成本计算结果还会微调,但是微调的值特别小,所以这里我就省略了,并且这里也只是大致介绍了成本计算的规则,实际情况会更复杂,比如连表查询等等,有感兴趣的小伙伴查阅相关的资料小结总的来说,这一节主要是让你明白一件事,mysql在选择索引的时候,会根据统计数据和成本计算的规则来计算使用每个索引的成本,然后选择使用最低成本的索引来执行查询索引失效在日常开发中,肯定或多或少都遇到过索引失效的问题,这里我总结一下几种常见的索引失效的场景为了方便解释,这里我再把图拿过来不符和最左前缀匹配原则当不符和最左前缀匹配原则的时候会导致索引失效比如like以%开头,索引失效或者是联合索引没走第一个索引列。比如name和age的联合索引,当执行select * from user where name > '王五' and age > 22;时,那么如果要走索引的话,此时就需要扫描整个索引,因为索引列是先以name字段排序,再以age字段排序的,对于age来说,在整个索引中来说是无序的,从图中也可以看出 18、23...9,无序,所以无法根据二分查找定位到age > 22是从哪个索引页开始的,所以走索引的话要扫描整个索引,一个一个判断,最后还要回表,这就很耗性能,不如直接扫描聚簇索引,也就是全表扫描来的痛快。索引列进行了计算当对索引进行表达式计算或者使用函数时也会导致索引失效这个主要是因为索引中保存的是索引字段是原始值,从上面画的图可以看出来,当经过函数计算后的值,也就没办法走索引了隐式转换当索引列发生了隐式转换可能会导致索引失效举个例子,mysql规定,当字符串跟数字比较时,会把字符串先转成数字再比较,至于字符串怎么转成数字,mysql有自己的规则比如说,当我执行了下面这条sql时就会发生隐式转换select * from `user` where name = 9527;

name字段是个varchar类型,9527,没加引号,是数字,mysql根据规则会把name字段的值先转换成数字,再与9527比较,此时由于name字段发生了转换,所以索引失效了

ALL说明没走索引,失效了。

但是假设现在对age创建一个索引,执行下面这条sql

这里我画了6条数据,假设有10w条数据那么也是这继续排,男在前,女子在后。此时如果走sex索引,查询sex=男的数据,假设男女数据对半,那么就扫描的记录就有5w,之后如果要回表,那么根据成本计算规则发现成本是巨大的,那么此时还不如直接全表扫描来的痛快。所以要选择区分度高的字段做索引总结到这,本文就结束了,这里回顾一下本文讲的内容首先主要是讲了聚簇索引和非聚簇索引,随后讲了MySQL对于一些常见查询的优化,比如覆盖索引,索引下推,都是为了减少回表次数,从而减少带来的性能消耗,再后面就提到MySQL是如何选择索引的,最后介绍了索引失效的场景和索引建立的原则。最后希望本文对你有所帮助!最后的最后,表数据sql如下INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (1, '李四', 20, '杭州');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (2, '张三', 18, '北京');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (3, '张三', 23, '上海');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (4, '赵六', 22, '杭州');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (5, '王五', 19, '北京');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (6, '赵六', 24, '上海');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (7, '刘七', 20, '上海');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (8, '刘七', 22, '上海');
INSERT INTO `user` (`id`, `name`, `age`, `city`) VALUES (9, '王九', 9, '杭州');

参考:

[1].《MySQL是怎么样运行的》

[2].https://blog.csdn.net/weixin_44953658/article/details/127878350