深入浅出Mysql(一)-Mysql索引底层数据结构与算法

189 阅读3分钟

带着问题看文章

  1. 索引数据结构红黑树、Hash、B+树是什么?
  2. 千万级数据表如何用B+树索引快速查找?
  3. 聚集索引、聚族索引、稀疏索引到底是什么?
  4. 为什么DBA总推荐使用自增主键做索引?
  5. 联合索引底层的数据又是怎么样的?
  6. Mysql最左前缀优化原则是怎么回事?

一、索引结构

前言

索引是帮助MySQL高效获取数据的排好序的数据结构。

1、红黑树

zhuanlan.zhihu.com/p/91960960

2、Hash

  • 对索引的key进行一次hash计算就可以定位出数据存储的位置
  • 很多时候Hash索引要比B+ 树索引更高效
  • 仅能满足 “=”,“IN”,不支持范围查询(工作中大部分都不会使用Hash的原因)
  • hash冲突问题

image.png

3、B树/B+树

(1)B树

  • 叶节点具有相同的深度,叶节点的指针为空
  • 所有索引元素不重复
  • 节点中的数据索引从左到右递增排列 image.png

(2)B+树

  • 非叶子节点不存储data,只存储索引(冗余),可以放更多的索引
  • 叶子节点包含所有索引字段
  • 叶子节点用指针连接,提高区间访问的性能 image.png

面试题:为什么Mysql选用了B+树而不是B树?

存储同样数据的时候,B+树的层数小于B树,所以有更好的查找性能。

因为一个节点最多存放16kb大小的数据,而带B树每一层每个节点都会带有数据,所以节点变大了每一层存的数据就变少了,层数就变大了。而B+树只有前两层都是冗余索引,因此可以带有更多的节点,层数就小了。

二、InnoDB存储引擎

1、索引类型

(1)聚集索引

是指索引和数据放在同一个文件夹下。

InnoDB是聚集索引 image.png

(2)非聚集索引

是指索引和数据放在不同文件夹下。

MyISAM索引文件和数据文件是分离的(非聚集) image.png

2、联合索引

(1)底层存储结构

image.png

(2)索引最左前缀原理

1、Select * from tableName Where name = "Bill" and age = 31;
2、Select * from tableName Where age = 30 AND position = 'dev';
3、Select * from tableName Where position = 'manger';

上面三条sql语句中只有第一条会走索引 在(1)的图中可以看到属性的顺序是name、age、position,名字是排好序的,但是age和position不一定是排好序的,所以才有最左前缀原理。

面试题:聚集索引和非聚集索引哪个更快?不考虑其他因素

答:“聚集索引”(非聚集索引还要跨文件查找数据)

面试题:为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?

InnoDB可以用自增主键来当索引维护这张表(具体参考上面的B+树)。

如果没有主键,那InnoDB会找到一列完全不相同的数据来当索引。

如果还是没有找到,那Mysql会维护一个虚拟列,该列内的id完全不相同,然后使用这个虚拟列rowid来维护这张表。数据库资源是宝贵的,没必要让Mysql帮我们做这些事情。

看到这里是不是认为只需要主键就可以了~

使用主键,更重要的是使用自增的索引,因为B+树底层是排好序的,低层的节点有双向指针,如果不自增的,Mysql可能还需要去帮你平衡这颗树。 image.png

面试题:为什么非主键索引结构叶子节点存储的是主键值(rowid)?

使用某一列来当索引,底层节点存储的是主键值(rowid),将来的查询会有回表的操作,这里主要是一致性和节省存储空间。

image.png

image.png