数据库
首页 > 数据库> > MySQL索引实现、MySQL索引原理、索引下推、索引覆盖、索引失效

MySQL索引实现、MySQL索引原理、索引下推、索引覆盖、索引失效

作者:互联网

文章目录

索引实现

https://www.cnblogs.com/jiawen010/p/11805241.html

目前MySQL的Innodb、Myisam存储引擎都是使用的B+树作为存储结构;

但是 memory存储引擎 确是 hash索引,所以索引数据结构要 结合 具体的存储引擎;


InnoDB索引实现

注意:一个索引节点就表示一个磁盘页

InnoDB的主键索引

InnoDB的聚簇索引 的 data域 存的是 行数据(具体数据)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sMwjYEUR-1620884626733)(13DC14EF3A9442128286BAE31CC79783)]

非叶子节点存的是 索引,叶子节点存的是数据;


InnoDB的辅助索引

InnoDB的所有辅助索引 的 data域 存的是 主键

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mHz5XTXi-1620884626737)(3B629EC68CE2496D8BB00F3FBA1F6FFE)]

辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录


MyISAM索引实现

MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aNT5Fp98-1620884626738)(AFC02E2F4DB44003868185B63BDF8708)]

在MyISAM中,主键索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复;


Innodb索引和MyISAM索引的区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iFsIHrc7-1620884626740)(0C273E2279E748E3834821AD30FE4352)]

  1. Innodb 主键使用的是聚簇索引,MyISam主键索引使用的是非聚簇索引;
  2. Innodb主键索引的叶子节点存放的是行记录,是具体的数据,Innodb非聚簇索引 叶子节点(data域)存放的是主键;而MyISam的聚簇索引和非聚簇索引都存放的是行数据的具体地址;

其它索引数据结构

hash索引的缺点

缺点: 因为底层数据结构是散列的,无法进行比较大小,不能进行范围查找

B+树和二叉查找树的性能对比

B树包括B+树的设计思想都是尽可能的降低树的高度,以此降低磁盘IO的次数,因为一个索引节点就表示一个磁盘页

一个索引节点就表示一个磁盘页;
假设一个节点可以容纳100个值,那么3层的B+树可以容纳100万个数据。
根节点100,第二层100*100,第三次存数据就是100x100x100,z三层只需3次io;

而如果使用二叉查找树,则需要将近20层,也就是进行20次磁盘IO;


B+对比B树的优点

B树的每个节点除了存储指向子节点的索引之外,还有data域,因此单一节点存储的指向子节点的索引并不是很多,树高度较高,磁盘IO次数较多,

个人理解,B树的索引节点,既存索引也存数据,一次io读取的数据是有限的,所以b树存的索引相对于b+树少,在数据量大的情况下,b树io次数多;

假设 一个索引可以存100单位数据,索引和data分别需要1单位,那么3层b树能存50+50x50+50x50*50个索引,而3层b+树可以存100x100x100,故b+树可以存更多索引;

总结:b+树的节点可以存更多索引数据,而b树的节点既要存索引,又要存数据,因此存的索引少;

其它关于索引数据结构的问题

为什么数据库索引不用红黑树而用B+树

红黑树在插入删除操作时需要 通过旋转和变色操作 来恢复二叉树性质;

但是当数据量较小,数据完全可以放入内存中,不需要进行磁盘IO,这时候,红黑树时间复杂度比B+树低。


索引失效

https://www.cnblogs.com/wdss/p/11186411.html

条件中or前后没有同时使用索引,索引失效

例如select * from user where name="zhsngsan" or id=29527;其中id是主键,那么id是主键索引,而name不是索引,则索引失效;

在这里插入图片描述

like 以%开头,索引失效

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7J8m91zo-1620884626743)(43C01175C79542B497BF88341C497E4E)]

当like前缀没有%,后缀有%时,索引有效。

组合索引,不是使用第一列索引,索引失效

https://zhuanlan.zhihu.com/p/108179618

例如 create index test2 on emp(ename , empno,job);,其中ename就是第一列索引,只要条件中不含ename组合索引就会失效;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ibTUXQEc-1620884626743)(4334FEC056244E41B8727FF598B28E06)]

数据类型出现隐式转化,索引失效

如varchar不加单引号的话可能会自动转换为int型,使索引无效;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w6SbE4Gw-1620884626744)(ACCAF859AD184449803B5D2E8AD58B3A)]

其它情况


不推荐使用索引的情况

  1. 数据唯一性差(一个字段的取值只有几种时)的字段不要使用索引

比如性别,只有两种可能数据。意味着索引的二叉树级别少,多是平级。这样的二叉树查找无异于全表扫描。

  1. 频繁更新的字段不要使用索引

比如logincount登录次数,频繁变化导致索引也频繁变化,增大数据库工作量,降低效率。

  1. 字段不在where语句出现时不要添加索引,如果where后含IS NULL /IS NOT NULL/ like ‘%输入符%’等条件,不建议使用索引

只有在where语句出现,mysql才会去使用索引

4) where 子句里对索引列使用不等于(<>),使用索引效果一般



覆盖索引

只需要在一棵索引树上就能获取SQL所需的所有列数据的索引成为覆盖索引(Covering Index),无需回表,速度更快。

//id是主键、name是索引,则下面sql需要回表,因为需要通过id回表获取sex;
select id,name,sex from user where name='shenjian';

但是,如果再创建一个联合索引(name,sex),那么上面的sql就不需要回表;因为通过(name,sex)的索引可以获取id,name,sex 不需要回表;

组合索引

最左匹配原则

https://chensj.blog.csdn.net/article/details/108540362

组合索引abc_index:(a,b,c),只会在where条件中带有(a)、(a,b)、(a,b,c)的三种类型的查询中使用使用索引。

当where条件只有(a,c)时也会走,但是只走a字段索引,不会走c字段。


注意

(a,b,c,d)建立索引,  
where后条件为a = 1 and b = 2 and c > 3 and d = 4  
那么,a,b,c三个字段能用到索引,而d就匹配不到。因为遇到了范围查询!

组合索引数据结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OCh7stYQ-1620884626744)(E3042C65C58B417A9E99505B1706E97D)]

联合索引中的索引项会先根据第一个索引列进行排序,第一个索引列相同的情况下,会再按照第二个索引列进行排序,依次类推。

例如联合索引abc_index:(a,b,c),sql where a=1and b=2 and c=3;
先根据a查询,a相同的情况下,b是排好序的,因此可以定位到b,同理c;

但是如果sql是where a=1,c=3;a会走索引得出主键,再根据主键回表查c;
因为a相同时,c是乱序的;

总结
联合索引(a,b,c)可以直接定位到a,ab,abc,至于ac需要2次定位;


索引下推

https://blog.csdn.net/luxiaoruo/article/details/106637231

https://blog.csdn.net/qq_34162294/article/details/105260154

在不使用索引下推的情况下,使用非主键索引进行查询时,存储引擎 通过索引检索到数据,然后返回给MySQL服务器,服务器做最后的筛选

例如查询gander=男 and age>20的数据,
不使用索引下推时,存储引擎将gander=男的数据直接返回 给mysql服务层,再由 服务层 根据age>20筛选出最终数据返回Clint;

使用索引下推后,存储引擎 直接筛选gander=男 and age>20的数据返回 给mysql服务层;


谓词下推

什么是谓词

谓词下推概念中的谓词指返回bool值即true和false的函数,或是隐式转换为bool的函数:

SQL中的谓词主要有 LKIE、BETWEEN、IS NULL、IS NOT NULL、IN、EXISTS。


谓词下推

https://blog.csdn.net/EdwardWong_/article/details/105970779

谓词下推 Predicate Pushdown:基本策略是,始终将过滤表达式尽可能移至靠近数据源的位置。

简而言之,就是在不影响结果的情况下,尽量将过滤条件提前执行。

select count(1) from A Join B on A.id = B.id where A.a > 10 and B.b < 100;

在处理Join操作之前需要首先对A和B执行TableScan操作,然后再进行Join,再执行过滤,最后计算聚合函数返回,但是如果把过滤条件A.a > 10和B.b < 100分别移到A表的TableScan和B表的TableScan的时候执行,可以大大降低Join操作的输入数据。优化后的语句如下:

select count(1) from (select *  from A  where a>10)A1 Join (select *  from B  where b<100)B1 on A1.id = B1.id;

标签:下推,节点,索引,MySQL,失效,where,主键
来源: https://blog.csdn.net/qq_43369986/article/details/116747163