索引常见模型
1,索引是为了提高数据查询效率,类似书的目录,借录目录可快速找到某一知识点。
2,实现索引的方式有多种,分别为哈希表、有序数组、搜索树。
1)哈希表以键-值存储数据,无序,增加数据较快往后追加即可,区间索引较慢,所以哈希结构适用于等值查询,例Memcached及NoSQL引擎。
2)有序数组在等值查询和范围查询场景中速度较快,但增加数据需要保持有序,当前插入位置后的数据都需要往后移动,成本较高,有序数组只适用于静态存储引擎,不会再修改的数据。
3)二叉搜索树的搜索效率高,但树高不可控,索引不止存在内存中,还要写到磁盘上,当二叉树高为N时,一次查询最多要访问N个数据块。
4)N叉树,N取决于数据块的大小。以InnoDB的整数字段索引为例,N差不多是1200,树高是4的时候,可以存1200的3次方个值,树的第一层、第二层数据块通常存在内存中,访问磁盘的平均次数就非常少了,查询中少读磁盘,少访问数据块。
InnoDB索引模型
1,在MySQL中,索引在存储引擎层实现,不同的存储引擎索引的工作方式不一样,在InnoDB中表是根据主键顺序以索引形式存放,这种存储方式称索引组织表。
2,InnoDB使用B+树索引模型,所以数据是存储在B+树中。
1)每一个索引对应一棵B+树。
2)根据叶子节点的内容,索引分为主键索引和非主键索引。
3)主键索引(也叫聚簇索引)的叶子节点存的是整行数据。
4)非主键索引(也叫二级索引)的叶子节点存的是主键的值。
3,基于主键索引的查询只需要搜索主键索引的B+树,普通索引则需要先搜索普通索引B+树得到主键值,再根据主键搜索一次,这个过程称为回表。
1)基于非主键索引的查询需要多扫描一棵索引树,应用中尽量使用主键索引。
2)普通索引搜索得到主键值,主键值即是查询结果,此过程称覆盖索引,不需要回表过程。
4,覆盖索引可以减少树的搜索次数,提升查询性能,但不可能为每一种查询设计一个索引。B+树可以利用索引的最左前缀,结合联合索引,例建立(a,b)的联合索引,维护(a,b)和b两个索引,不需要单独在a上建立索引,既可以满足a,b各自查询,也可以满足a,b的联合查询。
5,最左前缀可以是联合索引的最左N个字段,也可以是最左N个字符。建立联合索引时需评估索引的复用能力,调整顺序,尽可能少量维护索引,同时考虑空间原则:
1)b的单字段小于a,建立(a,b)的联合索引和b的单字段索引。
2)联合索引(a,b,c)的索引组织顺序相当于order by a,b,c,先按a排序,再按b排序,再按c排序。
6,MySQL5.6引入索引下推,可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足索引条件的记录,减少回表次数,在5.6之前则需要在找到满足条件的第一条记录开始一个个回表,到主键索引上找出数据行,再对比字段值。
7,覆盖索引、前缀索引、索引下推都是在满足语句需求的情况下,尽量少访问磁盘,在设计表结构时,需要以减少资源消耗作为目标。
8,B+树为了维护索引有序性,插入新值时,需要逻辑上挪动后面的数据,如果插入的数据页已满,需要申请新的数据页,将插入位置后的数据移动到新数据页,这个过程称为页分裂。
1)当相邻两个页因删除了数据导致利用率较低时,将数据页合并,合并的过程为分裂过程的逆过程。
2)数据删除或页分裂导致数据页的索引有空洞,可重建该索引,重建索引的过程会创建新的索引,把数据按顺序插入,页面利用率高,索引更紧凑且省空间,但不可重建主键,删除主键或创建主键,整个表都会重建。
9,自增主键是指自增列上定义的主键,建表时NOT NULL PRIMARY AUTO_INCREMENT,插入新记录时不指定主键值,系统会根据当前主键最大值+1作为下一条记录的主键值。
10,从性能和存储空间方面考虑,自增主键通常是更合理的选择。当业务需求场景只有一个索引,且必须是唯一索引时适用业务字段做主键。
1)自增主键每次插入都是追加操作,不挪动其他记录也不会触发叶子节点分裂。
2)业务逻辑的字段做主键,不容易保证有序插入。
3)非主键索引的叶子节点是主键的值,主键长度越小,普通索引的叶子节越小,普通索引占用空间也越小。