定义
索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构。
image.png
为什么要使用索引?
-
索引能极大的减少存储引擎需要扫描的数据量。
-
索引可以把随机I/O变成顺序I/O。
mysql 数据最终都会刷到磁盘上去,刷盘分随机IO和顺序IO,两者性能相差很大,大多情况下我们会改变一下设计使mysql 的随机IO变为顺序IO来提高性能。对随机I/O和顺序I/O想深入了解的可以看这篇文章:https://blog.csdn.net/dba_waterbin/article/details/8937441 -
索引可以帮助我们在进行分组、排序等操作时,避免使用临时表。
B+Tree
索引的存储数据结构是使用B+树进行构建的,使用二叉树来进行存储可以加快查找的速度。在介绍B+Tree之前,先介绍下二叉平衡查找树。如图
image.png
数据在构建时是参考如下结构:
image.png
在查找数据时,如果x<10.会走P1节点的引用,数据区是具体数据的地址。这个结构是一个平衡二叉树的数据结构,查找很快,但是仍然有如下的缺点:
如果数据量很大,达到几十万。
1.数据太深了,决定了它I/O操作的次数会很大。
2.每个磁盘块保存的数据量较小。没有很好的利用操作磁盘数据I/O的特性,mysql每次读取的页数大小为16k。
再来参考下如下这种数据存储的结构(解决了以上两个问题):
类似2-3树也叫做B树,所以很多关系型数据库都采用B树的数据结构方式作为存储索引的数据。
mysql采用B+Tree的结构来进行存储。
如图:
image.png
1,B+节点关键字搜索采用闭合区间(为了往右边进行一个数据的插入,就算查到id==1,也会继续往下面走)
2,B+非叶节点不保存数据相关信息,只保存关键字和子节点的引用
3,B+关键字对应的数据保存在叶子节点中
4,B+叶子节点是顺序排列的,并且相邻节点具有顺序引用的关系(保证数据天然具有排序能力)
好处(与B树的区别):
B+树是B-树的变种(PLUS版)多路绝对平衡查找树,他拥有B-树的优势
B+树扫库、表能力更强
B+树的磁盘读写能力更强
B+树的排序能力更强
B+树的查询效率更加稳定
利用好操作磁盘数据I/O的特性
Mysql中B+树索引的体现形式
Myisam
image.png
如图,在Myisam存储引擎中,每条数据对应保存一个引用地址(物理磁盘位置的一个指针),在查询时,根据B树索引找到对应数据的地址,然后根据地址,去加载数据的内容。ID列和name列的索引是平级的。建立索引后,会生成两个文件,分别是 .MYI和 .MYD为后缀的文件。但是innodb只有一个idb文件。
Innodb
image.png
是以主键为索引来组织数据的存储,如果没有主动建立索引,则会默认建一个隐式的六位数的一个主键索引。
Innodb是数据与关键字都存储在一起的,使用的是聚集索引。那么索引一旦建立会变成下面这样组织。
image.png
查找时,先基于name,找到101,然后再通过101,找到数据。先用辅助索引找到主键索引。为什么辅助索引不用一个地址,指向数据呢?
这样设计的考量在于,一旦主键索引中的数据发生变化,迁移,不需要回过头来维护辅助索引。
聚集索引: 数据库表行中的物理顺序与键值的逻辑顺序相同。
非聚集(unclustered)索引。
定义:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引.
如何解决非聚集索引的二次查询问题
复合索引(覆盖索引)
建立两列以上的索引,即可查询复合索引里的列的数据而不需要进行回表二次查询,如index(col1, col2),执行下面的语句
区别看这里: https://www.cnblogs.com/s-b-b/p/8334593.html
Innodb与Myisam的区别
image.pngMyisam引擎它的数据跟索引是分离的,而innodb的数据跟所有是放在一起的,看上图。
关于列的离散性
如图所示,在name这一列(第一列),离散型是最好的,选择性最好。而zoneDesc中,第一位是0开头的,后面是7,1,2,离散型还不够好重合的多。
最左匹配原则
对索引中关键字进行计算(对比),一定是从左往右依次进行,且不可跳过
image.png
索引的种类
单列索引与联合索引
单列索引
节点中关键字[name]
联合索引
节点中关键字[name,phoneNum]
单列索引是特殊的联合索引
联合索引列选择原则
1,经常用的列优先 【最左匹配原则】
2,选择性(离散度)高的列优先【离散度高原则】
3,宽度小的列优先【最少空间原则】
覆盖索引
如果查询列可通过索引节点中的关键字直接返回,则该索引称之为覆盖索引。
覆盖索引可减少数据库IO,将随机IO变为顺序IO,可提高查询性能
索引的使用规范
索引列的数据长度能少则少。
索引一定不是越多越好,越全越好,一定是建合适的。
匹配列前缀可用到索引 like 9999%,like %9999%、like %9999用不到索引;
Where 条件中 not in 和 <>操作无法使用索引;
匹配范围值,order by 也可用到索引;
多用指定列查询,只返回自己想到的数据列,少用select *;
最左匹配原则
联合索引中如果不是按照索引最左列开始查找,无法使用索引;
联合索引中精确匹配最左前列并范围匹配另外一列可以用到索引;
联合索引中如果查询中有某个列的范围查询,则其右边的所有列都无法使用索引;
网友评论