redis使用跳表不用B+数的原因是:redis是内存数据库,而B+树纯粹是为了mysql这种IO数据库准备的。B+树的每个节点的数量都是一个mysql分区页的大小(阿里面试)
还有个几个姊妹篇:介绍mysql的B+索引原理 参考:一步步分析为什么B+树适合作为索引的结构 以及索引原理 (阿里面试)
参考:二分查找法:各种排序算法的时间复杂度和空间复杂度(阿里)
关于mysql 存储引擎 介绍包括默认的索引方式参考:MySql的多存储引擎架构, 默认的引擎InnoDB与 MYISAM的区别(滴滴 阿里)
敲黑板:
每级遍历 3 个结点即可,而跳表的高度为 h ,所以每次查找一个结点时,需要遍历的结点数为 3*跳表高度
,所以忽略低阶项和系数后的时间复杂度就是 ○(㏒n),空间复杂度是O(n)
数据结构
实现原理
key查询方式
查找效率
存储大小
插入、删除效率
Hash
哈希表
支持单key
接近O(1)
小,除了数据没有额外的存储
O(1)
B+树
平衡二叉树扩展而来
单key,范围,分页
O(Log(n)
除了数据,还多了左右指针,以及叶子节点指针
O(Log(n),需要调整树的结构,算法比较复杂
跳表
有序链表扩展而来
单key,分页
O(Log(n)
除了数据,还多了指针,但是每个节点的指针小于<2,所以比B+树占用空间小
O(Log(n),只用处理链表,算法比较简单
对LSM结构感兴趣的可以看下cassandra vs mongo (1)存储引擎
问题
如果对以下问题感到困惑或一知半解,请继续看下去,相信本文一定会对你有帮助
- mysql 索引如何实现
- mysql 索引结构B+树与hash有何区别。分别适用于什么场景
- 数据库的索引还能有其他实现吗
- redis跳表是如何实现的
- 跳表和B+树,LSM树有和区别呢
解析
首先为什么要把mysql索引和redis跳表放在一起讨论呢,因为他们解决的都是同一种问题,用于解决数据集合的查找问题,即根据指定的key,快速查到它所在的位置(或者对应的value)
当你站在这个角度去思考问题时,还会不知道B+树索引和hash索引的区别吗
数据集合的查找问题
现在我们将问题领域边界划分清楚了,就是为了解决数据集合的查找问题。这一块需要考虑哪些问题呢
- 需要支持哪些查找方式,单key/多key/范围查找,
- 插入/删除效率
- 查找效率(即时间复杂度)
- 存储大小(空间复杂度)
我们看下几种常用的查找结构
hash
hash是key,value形式,通过一个散列函数,能够根据key快速找到value
关于hash算法 ,这也是阿里的必考题 深度的原理 我写了几篇博客:尤其是最后一篇resize ,以及resize之前与之后的hashmap的情况,
resize 参考:HashMap多线程并发问题分析-正常和异常的rehash1(阿里)
B+ 树:
注意 这是关于B+树的总结,如果你掌握到这个程度 是远远不够的,
请参考详细的B+树原理:一步步分析为什么B+树适合作为索引的结构 以及索引原理 (阿里面试)
B+树 的数据都在叶子节点,非叶子节点存放 索引
B+树是在平衡二叉树基础上演变过来,为什么我们在算法课上没学到B+树和跳表这种结构呢。因为他们都是从工程实践中得到,在理论的基础上进行了妥协。
B+树首先是有序结构,为了不至于树的高度太高,影响查找效率,在叶子节点上存储的不是单个数据,而是一页数据,提高了查找效率,而为了更好的支持范围查询,B+树在叶子节点冗余了非叶子节点数据,为了支持翻页,叶子节点之间通过指针连接。