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考炸了 学科也炸了 时间显然没有 以后 ...
随机推荐
- xcode7.1.1不能真机调试ios9.2系统设备的解决方法
转载自:http://www.cocoachina.com/bbs/read.php?tid-331335.html 前些天手机升级到iOS9.2版本号 xcode7.1还能真机測试. 昨晚更新xc ...
- kafka快速开始教程
此教程假设你刚刚开始没有任何 Kafka 或 ZooKeeper 数据.Kafka的控制台脚本在类Unix和Windows平台不同,Windows平台使用bin\windows\\代替bin/,脚本的 ...
- 如何將 MySQL 資料庫轉移到 Microsoft SQL Server 與 Azure SQL Database
MySQL 是相當常用之資料庫伺服器,而微軟雲端服務 Microsoft Azure 上 Azure SQL Database 是一個功能強大且經濟實惠的選擇,透過本篇文章,使用 SQL Server ...
- Atitit.php opcode虚拟机指令集 分类以及详细解释
Atitit.php opcode虚拟机指令集 分类以及详细解释 1. 指令集常用分类:: Mov移动指令 算数逻辑移位指令 跳转指令 Oo指令 类型转换指令 2. 与jvm clr指令集合对比 P ...
- Atitit.json类库的设计与实现 ati json lib
Atitit.json类库的设计与实现 ati json lib 1. 目前jsonlib库可能有问题,可能版本冲突,抛出ex1 2. 解决之道:1 2.1. 自定义json解析库,使用多个复合的js ...
- Hibernate使用注意事项
映射的POJO类型中如果有基本类型最好都是用包装类来代替: 注意关联关系的正确设置,一对一(主键方式.外键外键方式),一对多和多对多的配置,单向.双向的配置: 更新核心配置文件的mapping:如果是 ...
- kthreadd-linux下2号进程
参考: 1. linux常见进程与内核线程 2. Linux下2号进程的kthreadd--Linux进程的管理与调度(七) 本文中代码内核版本:3.2.0 kthreadd:这种内核线程只有一个,它 ...
- STL next_permutation(a,a+n) 生成一个序列的全排列。满足可重集。
/** 题目: 链接: 题意: 思路: */ #include <iostream> #include <cstdio> #include <vector> #in ...
- [已解决]pycharm报错:AttributeError: module 'pip' has no attribute 'main'
> 更新pip后,pycharm更新模块报错,经过一番查找,现提供两种解决办法. 报错片段信息如下: AttributeError: module 'pip' has no attribute ...
- ORA-06519: 检测到活动的自治事务处理,已经回退
写了一个函数,由于在定义时加入了 create or replace function F_计算结果(In_参数 varchar2) return number is --使用自治事务PRAGMA A ...