mysql(innodb)学习笔记之索引

学习mysql索引的笔记,有错望指出,万分感谢!!!
【mysql(innodb)学习笔记之索引】索引可以分为两类,一种是聚簇索引,一种是辅助索引(非聚簇索引)
在讲区别之前,需要先了解一下innodb引擎,innodb引擎是索引组织表,也就是说表中数据是按主键的顺序放在磁盘上的,而所谓的顺序,基本上就是索引(聚簇索引)了,所以说innodb引擎是索引组织表。
你可以想一下,既然表中的数据是按聚簇索引的顺序存放在磁盘的,那么数据存放的顺序是否可以有两个呢?答案是否定的,这也就是说聚簇索引只能有一个,表中的数据就是按照这个顺序存储在磁盘上的。
辅助索引(非聚簇索引)的话就没有这要求了,不限于一个。回到上一个论点,聚簇索引因为数据按这个顺序存放在磁盘上,所以只能有一个,然后辅助索引不限于一个,那是否是说辅助索引的话跟数据没关系,只是单纯的像字典一样的,可以让我们快速找到我们需要的数据的呢?(当然,有人可能会说,这只是我说的不限于一个,请慢慢看。。。)
这两种索引到这里大概有了一个基本的认识了,至于深入,那么必须去研究数据结构了。
以数据结构划分,我们一般使用索引的有两种,一种是b+tree,一种是hash,而b+tree也是数据存储在磁盘上使用的数据结构,我们先来看看mysql中数据的存储状态:


mysql(innodb)学习笔记之索引
文章图片
这是一个典型的b+tree(去掉双向链表,双向链表是mysql为了优化范围查询所做的优化),这样的数据结构明显查找的时间复杂度低了很多吧,而且在每一级索引查找都是使用折半查找,这在b+tree上有做了一次优化。我们所谓的数据库的瓶颈都是在磁盘的io上,mysql使用的是b+tree来存储数据,而b+tree具有高扇出性(高扇出性:磁盘的最小存储单位是扇区,而高扇出性是指IO少,从磁盘读取页速度快),b+tree的深度也就是2-3左右,io只需要2-3次,一般磁盘io速率大概一秒钟100次左右,也就是说一次查找只要0.02-0.03s。(这都是从书上看来的0.0,括号里大多数是自己理解的)
聚簇索引和辅助索引的区别: 言简意赅,叶子节点里数据块存的东西的区别,聚簇索引存的是数据行,也就是说存了所有的字段。辅助索引(非聚簇索引)存的是索引字段(创建索引的字段)加上主键,嗯,就是除了索引字段只有主键。
从这里能看出来,如果你想查除了辅助索引中有的字段,就需要根据主键去聚簇索引中查了。大致是这样的(mysql技术内幕innodb存储引擎中copy来的,haha):


mysql(innodb)学习笔记之索引
文章图片
如上图所示,如果通过辅助索引查需要的数据,且辅助索引中不存在该字段,那么io是6次,辅助索引三次,聚簇索引三次。至于为什么是三次,看前一张图是不是觉得,每个叶子节点有那么多数据块,怎么就只需要一次io就能找到呢。这就跟磁盘操作有关了,其实每次操作系统都是取一页的数据到内存中(也就是你看到的每个大框框,innodb默认每页16kb,每个叶子节点就是一页,其实b+tree的建立也是根据页来的,这需要你自己去研究了,比如说很多行记录,但是没有超过一页大小,那么没有根节点,就只有一个叶子节点,把该页读到内存中然后通过折半查找对应的数据行),然后在操作的,所以说io只有6次。
ok,这样看来辅助索引存的是主键(相对聚簇索引而言),跟真正的物理结构是没有关系的,那是否可以建多个呢?答案是肯定的,不相信你可以试一下。那么,有需要引出一个概念了,
联合索引: 联合,其实也就是多个字段建立索引,上面说到辅助索引如果查询没有的字段需要根据主键去聚簇索引中找,磁盘io翻倍了,那么是否可以通过建立联合索引来优化呢?这是肯定的,通过将常用字段建立联合索引确实可以优化辅助索引,优化查询效率。但是,字段并不是越多越好的。索引的好处是查找快,这毋庸置疑,但是建立和修改时候的平衡是要付出代价的,尤其是联合索引,牵一发而动全身。就跟avl树一样,当树不平衡了,需要通过一些手段来平衡,这是需要开销的。除了这个,看下面这种图(也是copy来的):


mysql(innodb)学习笔记之索引
文章图片
暂且把它看做a、b建立索引,可以看到,a是按照1、2、3这样排序下来的,但是b确实1、2、1、4、1、2这样的,也就是说,当建立一个这样的联合索引后,你可以通过a=?来使用该索引,但是如果你单独使用b=?是不能是用索引的。学过物理的都知道一个相对的概念,物体是否运动是相对的,这里一样,b排序是相对a而言的。看a=1是,b为1、2。。。。所以联合索引的字段需要自己衡量利弊(记得原来看过的视频说,联合索引就跟搭桥一样,比如说a,b,c的联合索引,你搭了a才能走到b,搭了b才能找到c,中间用了什么范围,模糊查询,就到不了b和c,也就是说如果前面的值不是固定的,b,c这种其实是无序的)
hash索引: 这个其实没什么好讲的,就是hash表,根据哈希值来存储,like,范围都不能使用该索引,只能是找相等的数据(至于存的是什么自己想了,haha)。
都是自己理解,有错望告知,万分感谢。。。

    推荐阅读