B-Tree vs LSM-tree
一。已排序文件的查找时间
对一个有N笔记录的已排序表进行二叉查找,可以在O(log2N)比较级完成。如果表有1,000,000笔记录,那么定位其中一笔记录,将在20
( log21,000,000 = 19.931) 个比较级内完成。从磁盘上读取一笔记录,与之后的比较键值操作相比,在花费的运行时间上,读取操作处于支
配地位。从磁盘读取记录的时间涉及到一个寻道时间和旋转延迟。
- 读写头沿径向移动,移到要读取的扇区所在磁道的上方,这段时间称为寻道时间(seek time)
- 通过盘片的旋转,使得要读取的扇区转到读写头的下方,这段时间称为旋转延迟时间(rotational latency time)。
一个7200(转/min)的硬盘,每旋转一周所需时间为60*1000ms/7200=8.33ms,则平均旋转延迟时间为8.33÷2=4.17毫秒(平均
情况下,需要旋转半圈)。如此,在1,000,000中定位一笔记录将会话花费20*8ms=160ms。
二。提升查找的索引
在上面的例子中,初始磁盘读取从2个因素限制了查找范围。这可以通过创建一个辅助索引来改善,这个索引包含每块磁盘块上的首笔记录
(稀疏索引)。这个辅助索引可能只有原始数据库的1%大小,它可以更快速地被检索。在辅助索引中查找入口可以告诉我们在主数据库中要读
去哪一块。创建辅助索引的窍门是可以重复地给辅助索引创建辅助索引。多层次的辅助索引,使得查找问题从约为log2N 磁盘读取开销的二分
查找,变成logbN 磁盘读取开销的查找,其中b为分块入口数目(b = 100 则logb1,000,000 = 3 次读取)。在实际中,如果主数据库被频繁查找,
辅助索引可能会存储在磁盘缓存中,所以它们不会产生磁盘读取。
三。插入和删除带来的麻烦
如果数据库不会改变,那么编制索引就很简单,如果他们会改变,那么管理数据库及其索引就变得非常麻烦。从数据库中删除记录不会引
起太大问题:索引可以保持不变,记录只需要标记为已删除。数据库仍然保持有序状态。如果会有很多删除,之后查找和存储就不再那么高效了。
在一个有序文件中进行插入将是个灾难,因为需要给插入的记录制造空间。在文件中第一笔记录后插入记录需要把所有记录向后偏移一个位置。
如此的操作在实际中实在太过昂贵。
一种做法是预留一些空间给插入操作。磁盘块有一些空闲空间允许后来的插入,而不是高密度地填充。
四。B树运用的理念
B树使用了以上所有的想法。特别是:
- 保持键值有序,以顺序遍历
- 使用层次化的索引来最小化磁盘读取
- 使用不完全填充的块来加速插入和删除
- 通过优雅的遍历算法来保持索引平衡
另外,B树通过保证内部节点至少半满来最小化空间浪费。一棵B树可以处理任意数目的插入和删除。
五。什么数据结构可以作为数据库索引
考虑到range查询, 所以hash索引不行。对于关系数据库, 基本都是用B+树作为索引机制, 而没有用二叉树或他的变种红黑树的, 为什么?
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以文件的形式存储的磁盘上。这样的话,索引查找过程中就要产
生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁
盘I/O操作次数
主存和磁盘以页为单位交换数据(在许多操作系统中,页得大小为4k), 页是计算机管理存储器的逻辑块, 这就意味着, 就算你只需要1byte
的数据, 每次也要读一页出来. 所以如果想要减少磁盘读取次数, 就需要合理的组织存储结构, 使每次读出的页中包含更多我们需要的信息.
可以想象在遍历索引树的时候, 如果所有的树节点都是存在磁盘上的, 那么我们需要访问节点的个数, 就是我们实际需要的磁盘I/O次数.
因为你无法保证你读出一个page里面包含你想遍历的多个节点.
对于索引树而言, 访问次数等于树高, 那么即树高越高的树型结构, 效率越低.所以对于平衡二叉树, 树高等于log2N, 明显效率太低.于是产生了B树,
B树就是增加每个节点的度, 度由2变成n, 这样树高大大降低, 一般实际只有3左右.
这个想法很自然, 我们使一个节点包含尽可能多的信息, 由2个分支到n个分支, 但是又要保证一个节点的信息必须在一个page中, 不能超出page大小.
在page大小固定的情况下, B树的度是由每个度的大小(keysize + datasize + pointsize)决定的, 当然希望B树的度尽量的大, 这样树高就
越低.这个就是B+树产生的原因, 因为在B树中节点是存放data的, 而在B+树中所以data都放到了leaf节点, 这样就是树节点的度得到了大大的
提高.而数据库实际使用的是带有顺序访问指针的B+Tree, 如图
在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能
六。如何解决高速读写
1. 尽可能快的写
对磁盘来说,最快的写入方式一定是顺序的将每一次写入都直接写入到磁盘中即可。但这样带来的问题是,我没办法查询,因为每次查询一个值
都需要遍历整个数据才能找到。 典型的例子是HDFS, 支持海量写和顺序读,不支持随机读。
2. 尽可能快的读
如果需要尽可能快的读到, 保持所有数据都是有序的,就可以很快的读到。 典型的例子就是B+树。但是需要保持全局有序, 必然会影响写的效率,
这就是B+树的问题:如果有大量的随机写, 每个写都可能需要操作不同的磁盘文件,效率很低,而且造成大量磁盘碎片,影响磁盘利用率
所以不可能同时达到读和写的快速, 最终的方案就是折衷,牺牲部分读速度, 来保证写速度。这个就是LSM-tree和SSTable的原理。
B-Tree vs LSM-tree的更多相关文章
- LSM Tree存储组织结构介绍
LSM Tree(Log Structured Merge Trees)数据组织方式被应用于多种数据库,如LevelDB.HBase.Cassandra等,下面我们从为什么使用LSM tree.LSM ...
- 数据映射-LSM Tree和SSTable
Coming from http://blog.sina.com.cn/s/blog_693f08470101njc7.html 今天来聊聊lsm tree,它的全称是log structured m ...
- 【万字长文】使用 LSM Tree 思想实现一个 KV 数据库
目录 设计思路 何为 LSM-Treee 参考资料 整体结构 内存表 WAL SSTable 的结构 SSTable 元素和索引的结构 SSTable Tree 内存中的 SSTable 数据查找过程 ...
- LSM Tree解析
引言 众所周知传统磁盘I/O是比较耗性能的,优化系统性能往往需要和磁盘I/O打交道,而磁盘I/O产生的时延主要由下面3个因素决定: 寻道时间(将磁盘臂移动到适当的柱面上所需要的时间,寻道时移动到相邻柱 ...
- LSM Tree 学习笔记——本质是将随机的写放在内存里形成有序的小memtable,然后定期合并成大的table flush到磁盘
The Sorted String Table (SSTable) is one of the most popular outputs for storing, processing, and ex ...
- LSM Tree 学习笔记——MemTable通常用 SkipList 来实现
最近发现很多数据库都使用了 LSM Tree 的存储模型,包括 LevelDB,HBase,Google BigTable,Cassandra,InfluxDB 等.之前还没有留意这么设计的原因,最近 ...
- Log-Structured Merge Tree (LSM Tree)
一种树,适合于写多读少的场景.主要是利用了延迟更新.批量写.顺序写磁盘(磁盘sequence access比random access快). 背景 回顾数据存储的两个“极端”发展方向 加快读:加索引( ...
- B-Tree、B+Tree和B*Tree
B-Tree(这儿可不是减号,就是常规意义的BTree) 是一种多路搜索树: 1.定义任意非叶子结点最多只有M个儿子:且M>2: 2.根结点的儿子数为[2, M]: 3.除根结点以外的非叶子结点 ...
- 【Luogu1501】Tree(Link-Cut Tree)
[Luogu1501]Tree(Link-Cut Tree) 题面 洛谷 题解 \(LCT\)版子题 看到了顺手敲一下而已 注意一下,别乘爆了 #include<iostream> #in ...
- 【BZOJ3282】Tree (Link-Cut Tree)
[BZOJ3282]Tree (Link-Cut Tree) 题面 BZOJ权限题呀,良心luogu上有 题解 Link-Cut Tree班子提 最近因为NOIP考炸了 学科也炸了 时间显然没有 以后 ...
随机推荐
- 解决window10系统电脑插入耳机之后没有声音的问题
其实办法也是从百度百科上查到的 ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄ 可能是因为自己某个不小心的操作更改了设置 1. 首先要点开设置按钮,在搜索栏输入控制面板 (当然知道控制面板在哪里的小伙伴就不用 ...
- VMware12.0下安装CentOS-6.9-x86_64-bin-DVD.iso
使用的是vmware workstation 12 pro 创建虚拟机 注意上面的 安装程序光盘镜象文件(iso)(M): 是我之前配置,现在可以不做任何处理 此处使用的是centos的64位 在创建 ...
- ActivityGroup window bad token问题深入分析
如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456 ActivityGroup window bad token问题深入分析 近期帮别人调试一个webview ...
- 【应用篇】Activiti外置表单实例demo(四)
在这里我想说的外置表单.是说我们将我们自己的jsp(.form,.html)等页面上传到工作流的数据库中,当任务运行到当前结点时.给我们像前台发送绑定好的表单. 此处是给表单绑定表单的过程 water ...
- atitit.跨语言执行cmd cli api的原理及兼容性设计草案
atitit.跨语言执行cmd cli api的原理及兼容性设计草案 1. 标准输入,标准输出,标准错误与重新定向1 2. 常见问题2 2.1. 执行bat文件2 2.2. 执行bat文件 /c ...
- 辛星让mysql跑的更快第一节之优化的方向和数据库建模
近期计划写一套书目,也就是关于mysql的优化的.那么首先在博客上写写,然后整理成pdf的文档的形式,当然也期待各位的关注了.对于mysql的优化是一个比較大的话题.可优化的地方也非常多,大致想了一下 ...
- testng入门_单元测试
1.定义TestNG 的配置文件 <test name="exampletest1"> <classes> <!--1.只执行com.t ...
- Spring Boot全日志设置
说在前面 这里日志分两种.一种是tomcat的输出(系统)日志,一种是自己定义的日志. 系统日志设置 目标 当springboot接收到请求时记录日志到文件中 实现 你只需要在你的绿叶applicat ...
- 使用Crypto++库编译出错 解决办法
错误信息: >------ 已启动生成: 项目: testCrypto++, 配置: Debug Win32 ------ >正在编译... >main.cpp >正在链接.. ...
- Spring @Transactional
在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例外(RunTimeExcep ...