- 索引是一种以数据库的一列或多列进行排序的数据结构
- 索引的出现是为了提高查询效率,索引就是树的目录,相当于数据库的目录
- 每碰到一个数据库要先关注它的数据模型,这样才能从理论上分析出数据库的应用场景
- 实现索引的三种主要方式
- 哈希索引
- 哈希表是一种以键值对存储的数据结构,查找效率高,对于哈希冲突的解决主要采用的还是链地址法
- 哈希表存储数据较快,同一条链上只需想后添加,缺点是数据无序,不适合做区间查询,适合做等值查询 (应用:mercached和其它NoSQL引擎)
- 有序数组
- 相比哈希索引,有序数组由于其有序性,适合做等值查询(使用二分法),但是当插入数据时,需要移动后面的记录
- 适用场景:静态存储引擎,比如保存某一年的城市人口信息,这一类不会再进行数据的修改场景
- 搜索树
- 平衡二叉搜索树的特点,有序,左孩子节点小于根节点,右孩子节点大于根节点,节点的更新查找都是logn的复杂度,查找效率很高
- 大多数的数据库存储引擎并不会选择二叉搜索树,因为索引不仅存在内存,还会存储在磁盘,对于二叉搜索树来说,树越高,每个磁盘页对应树的节点,需访问磁盘的次数越多,每一次磁盘读取都要寻道和旋转,会耗费大量的时间,因此每一次查询需要尽可能的少访问磁盘
- InnoDB是最常用的MySQL引擎,其索引结构使用的是B+树,为什么是B+树?
- B树和B+树的区别
- B树是平衡多路查找树是二叉查找树的变形,每个非叶子节点可以存在多个节点,每个节点存在多个关键字,每个节点的关键字按大小排序,关键字所有的左子树关键字均大于它,其右子树的关键字都大于它,节点的常见应用外存的读取,硬盘的读取以页为单位进行读取,而B树的节点元素(阶数)便可以调整为页的大小 查找时减少访问磁盘的次数
- 对于B树的遍历,我们需要往返于不同的节点,也就是对磁盘页面进行多次的访问(详见大话352),使得同一个元素会被访问多次。B+树是B树的变形
- 区别:
- B+树有两种类型的节点:内部结点(也称索引结点)和叶子结点。
- 内部节点就是非叶子节点,内部节点不存储数据,只存储索引,数据都存储在叶子节点。
- 内部结点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。
- 每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接。【相邻叶子节点存在指针,查找时从最左侧叶子节点出发,不用经过叶子节点,非常适合范围的查找】
- 父节点存有右孩子的第一个元素的索引。
- 优势:https://segmentfault.com/a/1190000020416577
- 查找效率稳定,所有查询都要查找到叶子节点
- 由于非叶子节点仅作为索引,能够存储更多的元素,使得io查询次数更少
- 查找时从最左侧叶子节点出发,不用经过非叶子节点,非常适合范围的查找
- B+树有两种类型的节点:内部结点(也称索引结点)和叶子结点。
- 选择B+树的原因和磁盘的局部性原理也有关系,磁盘是随机读取的,每次读取是通常是读取一页
- 每个索引在InnoDB对应一颗B+树,一张表可以存在多棵B+树
- 索引类型分为主键索引和非主键索引(二级索引)
- 主键索引的叶子节点存储的是整行数据
- 非主键索引叶子节点存储的主键的值
- 基于两种索引的查询区别,基于主键只需查询主键列的索引树,而基于非主键需先查询非主键列索引树得到主键,再查询主键列索引树【这种过程称之为回表】,多扫描一棵树,tip:尽量使用主键查询
- 索引维护
- 页分裂,B+树添加元素时,节点的元素大于阶数(这里可以认为是页大小),那么就会出现页分裂,出现数据的挪动,页分裂会影响数据页的利用率,空间利用率降低50%。当删除元素时,相邻页也会做页合并,分裂的逆过程
- 要不要用自增主键?(考虑索引的数据类型即索引大小)
- 自增主键的插入是递增的,都是追加操作,不会发生页分裂和数据挪动,而业务逻辑字段往往不能保证有序增加
- 另一方面存储角度,如果表中存在唯一字段身份证号(字符串类型),相比整形或或长整型要占用更大的存储空间,而主键长度越小,普通索引的叶子节点所占用的空间页越小
- 什么场景适合业务字段做索引
- 表中只有一个索引,并且是唯一索引 即kv场景(keyvalue)
- 哈希索引
深入浅出索引(上)
最新推荐文章于 2022-09-30 21:29:50 发布