请支持正版:MySQL实战45讲
索引出现其实就是为了提高数据查询的效率,就像书的目录一样
实现索引的方式很多种,常见的有三种:哈希表、有序数据和搜索树
这里不过多赘述哈希和哈希的原理
总结一下:
哈希实现索引的方式里,解决冲突的办法就是开链法
哈希表这种结构适用于只有等值查询的场景
有序数组则适用等职查询和范围查询,查询的方式是二分,时间复杂度是O(logn)
缺点就是更新数据的时候要挪动后面的所有记录,时间复杂度是O(n)
所以,有序数组只适用于静态存储引擎
,比如你保存的是历史数据,如2017年某月某城市的天气这种不会再修改的数据
二叉搜索树的相关知识这里也不多讲解,查询的时间复杂度也是O(logn),为了保证查询的时间复杂度,需要维护二叉搜索树,维护的时间复杂度也是O(logn)。
再往后就是多叉树,虽然二叉树的效率是最高的,但是实际数据库存储都不用二叉树,因为索引不止存在内存里,还要写到磁盘上
为了更快的查询,减少磁盘读的次数,采用了多叉树。
除了以上三种之外,还有跳表、LSM树等方式
在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里,也被称之为二级索引
既然有了这个划分,那么有一个问题:两种不同的索引从查询有什么区别?
回表
也就是基于非主键索引的查询需要多扫描一颗索引树,所以,我们应该尽量使用主键索引
B+树有诸多优点,但是维护B+树需要一些代价,有一条规则是内部节点(非叶子节点)的个数是有限制的,如果某个节点到达上限,称之为上溢,那么就需要新增一个节点,然后吧部分数据挪动过去,这个过程称之为页分裂
,这个过程不仅会影响性能还会影响空间利用率
你可能在一些建表规范里见到类似的描述,要求建表语句里一定要自增主键,当然事无绝对,我们来具体分析一下:
性能:
如果设置了自增主建,那么插入新记录的时候可以不指定ID的值,系统会获取当前ID最大值+1作为下一条记录的ID值,每一次插入新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂
而有业务逻辑的字段作为主键,往往不容易保证有序插入,这样写数据成本比较高
空间:
如果你表中确实有一个唯一字段,比如说身份证号,如果是用身份证号作为主键,那么每个二级索引的叶子节点占用20个字节,如果用整型则是4个字节,长整型则是8字节
所以,主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间越小
所以,从性能和空间方面考虑,自增主键往往是更合理的选择
有没有特例呢?显然是有的,如
其实就是KV场景,由于没有其他索引,那么就不用考虑其他索引叶子节点的大小问题
这时候我们只需要考虑到尽量使用主键查询
这个原则,把这个索引设置为主键,那么就可以避免每次查询会搜索两棵树了