为什么MySQL数据库存储数据建立索引使用B+树实现

这是大厂一道很经典的面试题吧,其实这个问题切入点就是其他的数据存储结构和B+树优缺点前提是你要知道其他的数据结构所以考察的范围还是挺广的,接下来我们一一分析。

1.为什么不用哈希+数组

哈希表(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里

举个简单的栗子,获取key的hashCode%数组长度 这样会得到一个小于数组长度的下标 这时候就可以将value存储在以该数字为下标的数组空间里。下次访问的时候直接通过key的hashCode方法%数组长度得到的下标找value即可,因为数组是有索引查找一个元素的时间复杂度是O(1)级别可以说最快那为什么没有使用这种数据结构呢?

select * from student where age>18 

大家想想如果用哈希加数组方式存储的范围查询怎么查 ,用key的hashCode方法%数组长度完全没有顺序关系 ,此时做范围查找显然要把所有数据全部遍历一遍才行所以没有采用这种数据结构,没有办法做范围查询或者说范围查询效率太低而在实际应用中范围查询必不可少

2.为什么不用二叉搜素树

BST AVL 红黑树都属于二叉搜索树此处以红黑树为例

上边说了用哈希加数组没有办法做范围查询那么我用红黑树左子树都小于当前结点右子树都大于当前结点这要就可以做范围查询了而且查询效率是log(n)级别的也是很快的那为啥不用呢?

这就涉及到硬件问题了数据库是在磁盘(固态和机械)存储的而磁盘读数据过程是非常耗时的

简单说下从磁盘读数据的大概流程(柱面 盘面 扇区大家查询相关资料自行了解)

寻道(就是找柱面的过程慢的时候能到0.1s这对计算机来说已经非常慢了)

旋转

传输

大家知道二叉树最多有二个分叉当数据特别多的时候肯定树的深度会特别高,这时候在查询叶子结点的时候会多次读磁盘数据这样会非常耗时的

而且还有一个问题数据库是以页的形式存储的MySQL InnoDB存储引擎默认 一页16K,一页可以看成一个结点 ,二叉树一个结点只能存储一个一个数据 假如索引字段为int 也就是一个数字要占16k的空间 大大的造成了空间浪费

2.1引申问题既然磁盘读数据这么费时间那么为什么Java HashMap TreeSet TreeMap还要用红黑树呢?

因为他们是在内存中运行的 没错就是因为这个, java程序启动是在jvm内存中运行的 你可以理解为cpu和内存的交互 要比cpu 和磁盘快很多(简单说一下有一个摩尔定律:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍 也就是18个月cpu的性能会提升一倍 而内存确跟不上 所以cpu 是通过cpu高速缓存Cache和内存交互的 而cpu和磁盘 其实他是先把磁盘的数据拿到内存 cpu再和内存交互)

 

3.使用 B+树优点

上面又说了二叉树只有二个叉 数据多树的高度会特别高而且二叉树一个结点只能存储一个值 ,所以需要一个N叉树一个结点还能存储多个数据的树结构 ,所以最后选择了 B+树

B-树

B+树

B-树和B+树的相对于数据库主要区别

B-树 N叉树并且一个结点可以存多个值 但是B-树每个结点存的是索引+数据 他其实并没有真正解决范围查频繁读磁盘数据的问题

虽然能清晰的知道范围但在查询的时候也要通过递归走一遍

而B+树非叶子节点只存储索引叶子结点才是真正的存储数据而且叶子结点之间是链式结构也就是双向链表 ,当我要查找一个小于一个数值范围的时候直接向左移动链表指针即可不用再递归到上一层再走左边 所以MySQL InnoDB存储引擎选择了B+树这种数据结构 最开始用的是B-树后边不断优化现在用的是B+树

4.引申问题 存储是基于索引值的比较 假如一个表没有主键索引 或者有多个主键索引这时候数据库是怎么存储的呢

4.1当数据库有多个索引的情况下遵循最左原则

PRIMARY KEY (id,name)

此时就用id(int)来构建这个表的B+树存储 比当前小的数据放左边  大的放右边

PRIMARY KEY (name,id)

此时就用name(varhcar)来构建这个表的B+树存储 也就是字典序比较

4.2当我没设主键索引的时候怎么存储呢

当你表中没有主键索引的时候 首先会找 unique 修饰的列 如果没有会找一个隐藏索引 

5.引申问题 B+树一个结点可以存多少数据 具体多少个呢 ?

这个存储个数和你设置索引字段类型 不同类型占不同的空间

假如 一条数据占1k 当前索引字段 占8字节 指针占6字节  一个页面 也就是一个结点是16k 

则一个高度为2的B+树可以存储 (16*1024/14)*16 =18720 条数据

刚才说了B+树只有叶子结点才存数据 所以 第一层一个结点 里边可以存  (16*1024/14) 这么多的索引

第二层就是叶子结点 总共有  (16*1024/14)叶子结点 每个叶子结点可以存16条数据 所以一个高度为2的B+树可以存储 18720 条数据

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值