MySQL实战45讲——04|深入浅出索引(上)

文章目录

  • 04|深入浅出索引(上)
    • 索引的常见模型
    • InnoDB的索引模型
    • 索引维护

04|深入浅出索引(上)

请支持正版:MySQL实战45讲

索引出现其实就是为了提高数据查询的效率,就像书的目录一样

索引的常见模型

实现索引的方式很多种,常见的有三种:哈希表、有序数据和搜索树

这里不过多赘述哈希和哈希的原理

总结一下:

  • 哈希实现索引的方式里,解决冲突的办法就是开链法

  • 哈希表这种结构适用于只有等值查询的场景

有序数组则适用等职查询和范围查询,查询的方式是二分,时间复杂度是O(logn)

缺点就是更新数据的时候要挪动后面的所有记录,时间复杂度是O(n)

所以,有序数组只适用于静态存储引擎,比如你保存的是历史数据,如2017年某月某城市的天气这种不会再修改的数据

二叉搜索树的相关知识这里也不多讲解,查询的时间复杂度也是O(logn),为了保证查询的时间复杂度,需要维护二叉搜索树,维护的时间复杂度也是O(logn)。

再往后就是多叉树,虽然二叉树的效率是最高的,但是实际数据库存储都不用二叉树,因为索引不止存在内存里,还要写到磁盘上

为了更快的查询,减少磁盘读的次数,采用了多叉树。

除了以上三种之外,还有跳表、LSM树等方式

InnoDB的索引模型

在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式称之为:索引组织表

InnoDB采用B+树索引模型,所以数据都是存储在B+树中,每一个索引对应一颗B+树

假设我们有一个主键为ID的表,表中有字段k,并且在k上有索引

这个表的建表语句如下:

mysql>create tableT(
	id int primary key,
    k int not null,
    name varchar(16),
    index (k)
)engine = InnoDB;

MySQL索引类型分为:主键索引和非主键索引

主键索引的叶子节点存的是整行的数据,在InnoDB中,主键索引也被称之为聚簇索引

非主键索引的叶子简单内容是主键的值,非主键索引在InnoDB里,也被称之为二级索引

既然有了这个划分,那么有一个问题:两种不同的索引从查询有什么区别?

  • 如果是select * from T where ID = 500;即主键查询,则只需要搜索ID这颗B+树
  • 如果是select * from T where k = 5,即普通索引查询,则需要先搜索k索引树,得到ID = 500,再到ID索引树搜索一次,这个过程称之为回表

也就是基于非主键索引的查询需要多扫描一颗索引树,所以,我们应该尽量使用主键索引

索引维护

B+树有诸多优点,但是维护B+树需要一些代价,有一条规则是内部节点(非叶子节点)的个数是有限制的,如果某个节点到达上限,称之为上溢,那么就需要新增一个节点,然后吧部分数据挪动过去,这个过程称之为页分裂,这个过程不仅会影响性能还会影响空间利用率

你可能在一些建表规范里见到类似的描述,要求建表语句里一定要自增主键,当然事无绝对,我们来具体分析一下:

性能:

如果设置了自增主建,那么插入新记录的时候可以不指定ID的值,系统会获取当前ID最大值+1作为下一条记录的ID值,每一次插入新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂

而有业务逻辑的字段作为主键,往往不容易保证有序插入,这样写数据成本比较高

空间:

如果你表中确实有一个唯一字段,比如说身份证号,如果是用身份证号作为主键,那么每个二级索引的叶子节点占用20个字节,如果用整型则是4个字节,长整型则是8字节

所以,主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间越小

所以,从性能和空间方面考虑,自增主键往往是更合理的选择

有没有特例呢?显然是有的,如

  • 只有一个索引
  • 该索引必须是唯一索引

其实就是KV场景,由于没有其他索引,那么就不用考虑其他索引叶子节点的大小问题

这时候我们只需要考虑到尽量使用主键查询这个原则,把这个索引设置为主键,那么就可以避免每次查询会搜索两棵树了

你可能感兴趣的:(MySQL实战45讲,mysql,数据库)