浅析B+索引以及使用

文章目录

    • 1、Mysql索引主要使用的两种数据结构
      • 1、B+树介绍
        • 为什么不使用B树?
      • 2、哈希索引
        • 优点:
        • 缺点:
      • 3、B树和B+树区别
    • 2、B+树索引的两种类型:聚集索引与辅助索引(非聚集索引)
      • 对比:
      • 聚集索引
        • 聚集索引的优点
        • 聚集索引的缺点
      • 非聚集索引
        • 非聚集索引的优点
        • 非聚集索引的缺点
      • 非聚集索引一定回表查询吗(覆盖索引)?
    • 3、B+树索引的使用
      • 联合索引
      • 覆盖索引

1、Mysql索引主要使用的两种数据结构

1、B+树介绍

mysql的innodb引擎使用B+树索引比较多

B+树索引给出具体的数据所在的页,读入到内存中,再从内存查找要的数据。

B+树是为磁盘或其他存储设备设计的一种平衡查找树,所有记录的节点按大小顺序放在同一层的叶子节点上,各叶子结点指针进行连接,形成双向链表。

高度一般在2到4层,机械磁盘一般每秒能至少100次IO,每次查询时间在0.02到0.04秒左右。

为什么不使用B树?

B树是一颗平衡二叉树,通过左旋或右旋来维持更新后的树的平衡性,开销较大。

2、哈希索引

对于哈希索引,InnoDB是自适应哈希索引的,根据表的使用情况自动生成哈希索引,不能人为干预。

对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,选择的是哈希索引,查询性能最快

优点:

1、Hash索引定位快

Hash索引指的就是Hash表,最大的优点就是能够在很短的时间内,根据Hash函数定位到数据所在的位置,这是B+树所不能比的。

缺点:

1、Hash冲突问题

在有大量重复键值情况下,哈希索引的效率也是极低的---->哈希碰撞问题。

知道HashMap或HashTable的同学,相信都知道它们最大的缺点就是Hash冲突了。不过对于数据库来说这还不算最大的缺点。

2、Hash索引不支持顺序和范围查询(最大的缺点)

试想一种情况:

SELECT * FROM tb1 WHERE id < 500;

B+树是有序的,在这种范围查询中,优势非常大,直接遍历比500小的叶子节点就够了。而Hash索引是根据hash算法来定位的,难不成还要把 1 - 499的数据,每个都进行一次hash计算来定位吗?这就是Hash最大的缺点了。

3、不支持最左匹配原则

3、B树和B+树区别

  • B树的所有节点既存放 键(key) 也存放 数据(data);而B+树只有叶子节点存放 key 和 data,其他内节点只存放key。
  • B树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
  • B树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。

2、B+树索引的两种类型:聚集索引与辅助索引(非聚集索引)

对比:

  • 聚集索引就是以主键创建的索引;非聚集索引就是以非主键创建的索引
  • 聚集索引在叶子节点存储的是表中的一整行数据;非聚集索引在叶子节点存储的是主键和索引列
  • 使用非聚集索引查询出数据时,拿到叶子上的主键再去查到想要查找的数据。(拿到主键再查找这个过程叫做回表)

聚集索引

聚集索引就是每张表的主键构造成一颗B+树,所以每张表只能有一个聚集索引。叶子结点存放着表的数据和结构,表的叶子节点称为数据页,每个数据页之间通过双向链表连接。

根节点页之间通过双向链表维护,按照主键顺序排序;叶子结点的数据页中的记录也是通过双向链表维护的,物理存储上可以不按照主键存储,而是按照逻辑存储,否则维护的开销过大。

在 Mysql 中,InnoDB引擎的表的 .ibd文件就包含了该表的索引和数据,对于 InnoDB 引擎表来说,该表的索引(B+树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据。

聚集索引的优点

聚集索引的查询速度非常的快,因为整个B+树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。

对于主键的排序查找和范围查找速度很快。

聚集索引的缺点

  1. 依赖于有序的数据 :因为B+树是多叉平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或UUID这种又长又难比较的数据,插入或查找的速度肯定比较慢。
  2. 更新代价大 : 如果对索引列的数据被修改时,那么对应的索引也将会被修改,
    而且况聚集索引的叶子节点还存放着数据,修改代价肯定是较大的,
    不过对于主键索引来说,主键一般都是不可被修改的。

非聚集索引

辅助索引的叶子结点并不存放行记录的全部数据,除了包含键值外,还包含了一个书签,告诉了Innodb对应的聚集索引键。

二级索引属于非聚集索引。

MYISAM引擎的表的.MYI文件包含了表的索引,
该表的索引(B+树)的每个叶子非叶子节点存储索引,
叶子节点存储索引和索引对应数据的指针,指向.MYD文件的数据。

非聚集索引的叶子节点并不一定存放数据的指针,
因为二级索引的叶子节点就存放的是主键,根据主键再回表查数据。

非聚集索引的优点

更新代价比聚集索引要小 。非聚集索引的更新代价就没有聚集索引那么大了,非聚集索引的叶子节点是不存放数据的

非聚集索引的缺点

  1. 跟聚集索引一样,非聚集索引也依赖于有序的数据
  2. 可能会二次查询(回表) :这应该是非聚集索引最大的缺点了。 当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。

非聚集索引一定回表查询吗(覆盖索引)?

非聚集索引不一定回表查询。

试想一种情况,用户准备使用SQL查询用户名,而用户名字段正好建立了索引。

 SELECT name FROM table WHERE username='guang19';

那么这个索引的key本身就是name,查到对应的name直接返回就行了,无需回表查询。

即使是MYISAM也是这样,虽然MYISAM的主键索引确实需要回表,
因为它的主键索引的叶子节点存放的是指针。但是如果SQL查的就是主键呢?

SELECT id FROM table WHERE id=1;

主键索引本身的key就是主键,查到返回就行了。这种情况就称之为覆盖索引了。

3、B+树索引的使用

联合索引

联合索引是指对表上的多个列进行索引。联合索引的键值的数量大于等于2,好处是对于每个键值都会做排序。当根据多个列来查询数据时能加快查询的速度。但是要根据匹配的顺序来决定是否能使用索引,例如索引列的顺序为(a,b,c),则根据a和c来查询是不能匹配到索引的。

覆盖索引

如果一个辅助索引包含所有需要查询的字段,那么我们就可以直接根据这个索引找到数据,而不用再回表查询聚集索引,这样的索引我们就称之为“覆盖索引”。我们知道InnoDB存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次。这样就会比较慢。

如主键索引,如果一条SQL需要查询主键,那么正好根据主键索引就可以查到主键。

再如普通索引,如果一条SQL需要查询name,name字段正好有索引,
那么直接根据这个索引就可以查到数据,也无需回表。

好处:覆盖索引的叶子节点不像聚集索引一样包含整行的所有信息,只包含对应字段的信息,故其大小远小于聚集索引,大大地减少了IO操作。

参考:《MYSQL技术内幕 InnoDB存储引擎》第二版

你可能感兴趣的:(数据库,mysql)