谈谈对数据库索引的理解?
关于作者
- 作者介绍
🍓 博客主页:作者主页
🍓 简介:JAVA领域优质创作者🥇、一名初入职场小白👨💻、在校期间参加各种省赛、国赛,斩获一系列荣誉🏆、阿里云专家博主、51CTO专家博主
🍓 关注我:关注我学习资料、文档下载统统都有,每日定时更新文章,励志做一名JAVA资深程序猿👨💻
B+树的存储特点:
局部性原理:
- 时间局部性:之前被查询过的数据很快可能被再次查询
- 空间局部性: 数据和程序都有聚集成群的倾向,具备某一个特点的数据经常聚集存储
- 磁盘预读:磁盘跟内存在进行交互的时候有一个最基本的逻辑单位,称之为页,每次在进行数据读取的时候一般读取的是页的整数倍,页的大小是跟操作系统相关,默认是4k或者8k,在mysql的innodb存储引繁中,默认是16kb
基于上述理论:数据读取的时候要分块读取,每次读取一部分数据,然后根据指针再次读取下一个块的数据。尽可能少的产生io次数,能读一次绝对不读两次尽可能少的读取数据,减少整体的io量。
为什么不使用哈希表做存储?
- hash比较浪费内存空间,而内存是非常宝贵的资源
- memory存储引掌支持的是hash索引
- innodb存储引擎支持自适应hash (由mysql自己来决定使用的是hash索引还是B+树索引,人为不能干预,由系统判断,只适用于innodb存储引擎)
为什么不使用二叉树、BST、AVL、红黑数?
每一个分支有且尽有两个子节点,当需要向其中插入更多的数据的时候,就必须要增加树的高度,而增加树的高度会导致树变深,会导致io的次数变多,所以所有的二叉树都是不建议使用的。根据结构不要求高,要求变胖,由此想到用多叉有序树,如B-树、B+树。
B树
实例图说明:
每个节点占用一个磁盘块, 一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为16和34, P1 指针指向的子树的数据范围为小于16, P2 指针指向的子树的数据范围为16~34。P3 指针指向的子树的数据范围为大于34。
查找关键字过程:
磁盘块1
读入内存。[磁盘 /O操作第1次]
磁盘块1
的指针P2。磁盘块3
,读入内存。[磁盘 l/0操作第2次]
磁盘块3
的指针P2。磁盘块8
,读入内存。 [磁盘1/O操作第3次]
磁盘块8
中的关键字列表中找到关键字28。缺点:
B+树
B+Tree是在BTree的基础之上做了的一种优化,变化如下:
- 第一个原因是为了降低树的高度
- 第二个原因是将数据范围变为多个区间,区间越多,数据检索越快
注意:在B+Tree上有两个头指针,一个指向根节点。另一个指向关键字最小的叶子节点。而且所有叶子节点(即数据节点)之间是一种链式
环结构。因此可以时B+Tree进行两种查询操作:一种是对于主键的查找和分页查找, 另一种是从根节点开始, 进行随机查找。
索引的使用场景和优化点
执行计划中,可以回表、索引覆盖、最左匹配、索引下推。