5.innodb B+tree索引

索引基础

索引是数据结构

1、图例

2、B+tree

  • 特征
    1、非叶子节点不保存数据,只用来索引,数据都保存在叶子节点
    2、查询任何一条数据,查询的索引深度都是一样的
    3、 B+ 树中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的,所有叶子节点形成有序链表,方便范围查询
    4、所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素
    5、B+树索引并不能根据键值找到具体的行数据,B+树索引只能找到行数据所在的页,然后通过把页读到内存,再在内存中查找到行数据

3、聚集索引 和 辅助索引

  • 聚集索引是按表的主键顺序构造的B+树,叶子节点存放的为整张表的行记录数据,每张表只能有一个聚集索引

  • 辅助索引也叫非聚集索引,叶子节点除了键值以外还包含了一个bookmark,就是相对应行数据的聚集索引键,然后通过主键索引来找到一个完整的行数据。这个再根据聚集索引查找数据的过程,我们称为回表

我们重点关注聚簇索引,看上去InnoDB的效率明显要低于MyISAM,因为每次使用辅助索引检索都要经过两次B+树查找,而MyISAM的非聚集索引使用辅助键查询只需要一次就能找到一整行的元组数据。这不是多此一举吗?
聚簇索引的优势在哪?

  1. 由于行数据和叶子节点存储在一起,这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,而不用再通过存储的地址再去硬盘中查询一次数据行,如果按照主键Id来组织数据,获得数据更快。
  2. 辅助索引使用主键作为"指针" 而不是使用地址值作为指针的好处是,减少了当出现行移动或者数据页分裂时辅助索引的维护工作,使用主键值当作指针会让辅助索引占用更多的空间,换来的好处是InnoDB在移动行时无须更新辅助索引中的这个"指针"。也就是说行的位置(实现中通过16K的Page来定位,详细可以看计算机操作系统分页管理相关章节)会随着数据库里数据的修改而发生变化(B+树节点分裂以及Page的分裂),使用InnoDB就可以保证不管这个主键B+树(聚集索引)的节点如何变化,辅助索引树(非聚集索引)都不受影响。
  3. 聚集索引的数据都是按顺序存放的,所以如果查询条件是主键,使用主键索引,那么聚集索引会非常快,因为相同范围段的数据都是连续存放在一起的。即聚集索引表记录的物理排列顺序与索引的逻辑排列顺序一致,优点是查询速度快,一旦符合条件的第一个索引值的纪录被找到,具有连续索引值的记录也一定物理的紧跟其后。聚集索引的主键索引的叶子节点中直接存储行数据,又因为B+树的叶子节点之间都会用过指针相连,所以直接就能很快将这个范围内的数据全部获取。但是非聚集索引的主键索引虽然在逻辑上相同范围的叶子节点是顺序存储在一起的,但是真实的行数据是在硬盘中散列存储的,要想获取数据还需要将存储在叶子节点中的地址取出,根据地址再去硬盘中获取数据,效率就慢了很多。这个是聚集索引的主键索引的优势,也是第一条优势的具体体现。根据局部性原理,这也会提高检索效率。
  • 局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中。

聚集索引的劣势有哪些?

  1. 聚集索引的缺点是对表进行修改速度较慢,这是为了保持表中的记录的物理顺序与索引的顺序一致,而把记录插入到数据页的相应位置,必须在数据页中进行数据重排,降低了执行速度。插入数据时速度要慢(时间花费在“物理存储的排序”上,也就是首先要找到位置然后插入)。而非聚集索引指定了表中记录的逻辑顺序,但记录的物理顺序和索引的顺序不一致,聚集索引和非聚集索引都采用了B+树的结构,但非聚集索引的叶子层并不与实际的数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针的方式(这个指针可能是真实的物理地址,也可能是对应的主键值,这根据不同的存储引擎对它实现是不同的)。非聚集索引比聚集索引层次多,添加记录不会引起数据顺序的重组。

总的来说,聚集索引查询数据速度快,插入数据速度慢;非聚集索引反之。他们各自优缺点就是相反的。所以非聚集索引的优缺点看上面聚集索引的优缺点就够了。

4、优缺点

优点:
	1、index是帮助MySQL高效获取数据的数据结构
	2、降低IO使用率
	3、降低CPU使用率(排序)
	4、数据即索引,索引即数据
缺点:
    1、索引要占用存储空间
    2、索引不是所有情况均适用:
       a、少量数据 
       b、频繁更新的字段
       c、很少使用的字段
	3、降低增删改的效率,增删改的同时还有对索引进行维护

5、语法

创建索引
	1、create [unique] index index_name on tablename(colunm[,col,…])
	2、alter table tabname add [unique] index index_name(colunm[,col,…]])
删除索引
	1、alter table tabname drop index index_name
	2、drop index index_name on tabname

6、索引类型

  • 单值索引
  • 多值索引
  • 唯一索引
posted @ 2020-12-18 11:33  罐头鱼  阅读(98)  评论(0编辑  收藏  举报