MySQL总结(二)——MySQL索引

MySQL 的基本存储结构

MySQL的基本存储结构是
各个数据页可以组成一个双向链表,每个数据页中的记录又可以组成一个单向链表

所以说,如果我们写select * from user where indexname = 'xxx’这样没有进行任何优化的sql语句,默认会这样做:

  1. 定位到记录所在的页:需要遍历双向链表,找到所在的页
  2. 从所在的页内中查找相应的记录:由于不是根据主键查询,只能遍历所在页的单链表了
    很明显,在数据量很大的情况下这样查找会很慢!这样的时间复杂度为O(n)

使用索引之后,会对索引字段构建一个B+树,其实就是将无序的数据变成有序(相对),通过二分查找,快速定位数据,时间复杂度近似为O(logn)

MySQL索引简介

MySQL索引使用的数据结构主要有BTree索引哈希索引。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。

BTree索引

MySQL的BTree索引使用的是B树中的B+Tree,但对于主要的两种存储引擎的实现方式是不同的。

  1. MyISAM: B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。
  2. InnoDB: 其数据文件本身就是索引文件。相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引(或聚集索引)”。而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方。在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,再走一遍主索引。 因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。
最左前缀原则(主要使用在联合索引中)

MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。
如User表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。

例如:
在这里插入图片描述
如果我们按照 name 字段来建立索引的话,采用B+树的结构,大概的索引结构如下
在这里插入图片描述
如果我们要进行模糊查找,查找name 以“张"开头的所有人的ID,即 sql 语句为:

select ID from table where name like '张%'

由于在B+树结构的索引中,索引项是按照索引定义里面出现的字段顺序排序的,索引在查找的时候,可以快速定位到 ID 为 100的张一,然后直接向右遍历所有张开头的人,直到条件不满足为止。
也就是说,我们找到第一个满足条件的人之后,直接向右遍历就可以了,由于索引是有序的,所有满足条件的人都会聚集在一起。

而这种定位到最左边,然后向右遍历寻找,就是我们所说的最左前缀原则。

主键索引和非主键索引

例如对于下面这个表(其实就是上面的表中增加了一个k字段),且ID是主键。
在这里插入图片描述
主键索引和非主键索引的示意图如下:

在这里插入图片描述
其中R代表一整行的值。

从图中不难看出,主键索引和非主键索引的区别是:非主键索引的叶子节点存放的是主键的值,而主键索引的叶子节点存放的是整行数据,其中非主键索引也被称为二级索引,而主键索引也被称为聚簇索引。

根据这两种结构我们来进行下查询,看看他们在查询上有什么区别。

  1. 如果查询语句是 select * from table where ID = 100,即主键查询的方式,则只需要搜索 ID 这棵 B+树。
  2. 如果查询语句是 select * from table where k = 1,即非主键的查询方式,则先搜索k索引树,得到ID=100,再到ID索引树搜索一次,这个过程也被称为回表。
发布了75 篇原创文章 · 获赞 39 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/s2152637/article/details/100825711