作者:林伯勋玉萍竣梅 | 来源:互联网 | 2023-08-07 19:35
索引是怎样工作的?索引的出现是提高数据查询效率,就像教科书中的目录一样。索引的常见模型哈希表哈希表是一种以键值存储的结构,我们只需要输入待查找的键即为key,就可以找到对应的值Va
索引是怎样工作的?
索引的出现是提高数据查询效率,就像教科书中的目录一样。
索引的常见模型
哈希表
哈希表是一种以键值存储的结构,我们只需要输入待查找的键即为key,就可以找到对应的值Value.哈希的思路很简单,把值放大数组里,用一个哈希函数把key换算成一个确定的位置,然后把value放在数组的这个位置
多个key值经过哈希函数换算,会出现同一个值的情况。处理这种情况的方法是拉链法
哈希索引做区间查询的速度很慢
哈希表这种结构适用于等值查询场景,比如Memcached及其他一些,NoSQL引擎
有序数组
搜索树
- 二叉搜索树:父节点的左子树所有节点的值小于父节点的值,右子树所有节点的值大于父节点的值,为了维持O(log(N))的时间复杂度,就需要保证这棵树更新时间复杂度为O(log(N))
- 二叉树的搜索效率是最高的,但是实际大多数的数据库存储却不使用二叉树,其原因。索引不止存在内存中,还要写在磁盘上。
- 如果一棵树100万个节点的平衡二叉树,树高20.一次查询可能需要访问20个数据块。在机械硬盘时代,从磁盘随机读一个数据块需要10ms左右的寻址空间,也就是说,对于100万行表,如果使用二叉树来存储,单独访问一个行可能需要20个10ms,这个查询速度太慢了
- 为了减少查询尽量少的读取磁盘,就必须查询过程访问尽量少的数据块,那么,我们就不该用二叉树,而是用N叉树
以 InnoDB 的一个整数字段索引为例,这个 N 差不多是 1200。这棵树高是 4 的时候,就可以存 1200 的 3 次方个值,这已经 17 亿了。考虑到树根的数据块总是在内存中的,一个 10 亿行的表上一个整数字段的索引,查找一个值最多只需要访问 3 次磁盘
N叉树由于读写上的性能特点,以及适配磁盘的访问模式,已经被广泛应用在数据库引擎中
Innodb索引模型
基于主键索引和普通索引的查询区别是什么?
- 根据主键索引查询方式,只需要搜索ID这棵树B+树
- 则需要先搜索K索引树,得到ID值500,再到ID索引树搜索一次,这个过程称为回表
索引维护
B+树为了维护索引有序性,在插入新值的时候需要必要的维护
如果插入ID为700直接在R5后面插入即可,如果插入400需要逻辑上面挪动后面的数据,如果R5所在数据页已经满了,根据B+树算法,这时候需要申请一个数据页,然后挪动部分数据过去,这个过程叫做页分裂,这种情况下性能会下降
除了性能外,页分裂操作还会影响数据页利用率,原本放在一个页的数据分为两页,整体空间利用率降低50%
当相邻两个页由于删除了数据,利用率很低之后,会将数据页做合并。合并的过程,可以认为是分裂过程的逆过程。
自增主键每次插入一条新纪录都是追加操作,都不涉及到挪动其他记录,也不会触发叶分裂
只有一个索引,该索引必须是唯一索引的时候可以考虑业务字段作为主键
Innodb使用了B+树结构,B+树能够很好地配合磁盘读写特性,减少单次查询磁盘访问次数。由于Innodb是索引组织表,一般情况下我会建议你创建一个自增主键,这样非主键索引占用空间最小
- 由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段
最左前缀原则
B+树这种索引结构,可以利用索引的最左前缀,来定位记录,联合索引考虑空间与复用
索引下推
检索出表中“名字第一个字是张,而且年龄是 10 岁的所有男孩”。那么,SQL 语句是这么写的:
mysql> select * from tuser where name like '张%' and age=10 and ismale=1;
Mysql5.6引入索引下推优化,可以索引遍历过程中,对索引包含的字段先做判断,直接过滤掉不满足的记录,减少汇报次数。InnoDB在(name,age)索引下推的过程中判断age的存在,减少一次次数