日志结构合并树
前言
就目前互联网环境而言非关系型数据库越来越受到青睐,其中较多的有hbase,leveldb以及公司所使用的clickhouse
数据结构定义
- LSM树是一个横跨内存和磁盘的,包含多颗"子树"的一个森林。
- LSM树分为Level 0,Level 1,Level 2 … Level n 多颗子树,其中只有Level 0在内存中,其余Level 1-n在磁盘中。
- 内存中的Level 0子树一般采用排序树(红黑树/AVL树)、跳表或者TreeMap等这类有序的数据结构,方便后续顺序写磁盘。
- 磁盘中的Level 1-n子树,本质是数据排好序后顺序写到磁盘上的文件,只是叫做树而已。
- 每一层的子树都有一个阈值大小,达到阈值后会进行合并,合并结果写入下一层。
- 只有内存中数据允许原地更新,磁盘上数据的变更只允许追加写,不做原地更新。
数据操作
插入
LSM tree 主要是在对L0 也就是内存上进行操作 以AVL为例 分为两种情况
- 当插入的叶子节点已存在
- 当插入的叶子节点不存在
lsm中为了对写入效率进行提升其中允许数据进行冗余所以在进行数据插入的时候以叶子节点1为例进行数据插入都会在L0的数据中进行插入,所以在磁盘空间中可能存在多个节点为1的数据其中在进行数据查询的时候L0 - Ln的层级访问获得最新的数据即可
删除
对数据进行删除这边引入了一个方式叫删除标记也就是对某个数据追加一个删除的标记字段。数据删除分为两种情况
- 待删除数据在内存中
- 待删除数据在磁盘中
上图为1情况下删除值为1节点数据的时候追加 del 字段
上图则是在待删除数据不在内存中则在内存中新增该节点 随着内存文件block到磁盘
修改
- 修改数据在内存中 :待修改数据直接在内存中进行更新
- 修改数据在磁盘中:待修改的数据直接以追加的方式写入L0内存中 随着Lo 落盘进行序列化
- 修改数据不存在:当需要修改的数据不存在时候则进行新增操作,详见插入操作
查询
相对于B+ tree的查询方式 LSM tree的查询分L0 也就是内存中 和磁盘中两种情况
- 待查询数据在内存中时,如果选择AVL tree 则查询效率为log(n)
- 待查询数据不在内存中(磁盘中或不存在)复杂度O(n)
合并
- 内存中写入磁盘文件(L0 -> L1):当L0达到设置的大小后对AVL tree 进行中序遍历获得排序后的信息再归入L1 层级中 进行数据落盘
- 磁盘文件进行归并操作(L 1 -> L2):当L1文件大小达到阈值后会进行L1内的所有的小文件排序操作合并后归入L2层级 批量重新写入
优缺点分析
优点:
从上述的文件操作不难看出 LSM 无论是进行增加还是删除 修改的操作 都不会对已有的磁盘文件进行操作而是以追加的方式对磁盘内的数据进行写入这样保证了批量数据的顺序写入极大的实现了数据告诉写入。
缺点:
在进行数据查询的时候如果查询的是不存在的数据则会从L0遍历到Ln层级影响了查询效率,且在数据存储的时候由于不对之前的数据做修改操作所以使得数据大量冗余。