存储引擎
面向日志
问题:数据量大时由于需要遍历整个日志文件,性能急剧下降
-
解决方案:索引
-
索引写性能弱于追加文件的性能
-
方案一:HASHMAP保存KEY->文件偏移量
-
实例:bitcask
-
适用场景:KEY数不多,但更新频繁的场景,索引可以放在内存
-
单个日志文件过大时,关闭该文件,开启新的日志段文件,对旧的段日志文件进行重写压缩
- 相关实例:REDIS AOF重写
-
段文件之间也可以进行合并,每个段维护各自的HASHMAP
- 合并旧段可防止文件碎片化问题
-
当客户端请求KEY时,先查询最新段文件对应的HASHMAP,没有再找第二最新,依此类推
-
并发时,由于追加写文件,只有一个写线程,而读可以有多个线程
-
存在问题
-
数据库重启或机器重启HASHMAP丢失,从段日志文件恢复时如果文件比较大,恢复时间会很长
- 解决方案:Bitcask对hashmap进行快照,并存储在磁盘
-
写日志时数据崩溃,日志文件不完整
- 解决方案:记录增加校验和,检验不通过丢弃数据
-
HASHMAP需要全部加载至内存,如果在磁盘上维护,会有大量的随机IO导致性能下降
-
连续性区间查询如bag-book效率低,需要逐个查询
-
-
-
方案二:SSTable
-
实例:LevelDB RocksDB Hbase Lucene的倒排索引(KEY为单词,VALUE为文档ID)
-
方案一内存中存储了所有键的HASHMAP,将日志文件的key-value按key排序,就可以不必保存所有KEY的HASHMAP,减少HASHMAP的存储量
- 节约内存空间
- 键排序后获取连续性的键值时可进行顺序读
-
具体实现方案
-
在内存中借助红黑树或AVL树维护一张内存表
-
当内存表大小阈值超过一定值时,将内存表落盘(此时磁盘上的KEY是排序的),创建新的内存表实例
-
落盘时,SSTable通常会进行分层合并,每一层文件保存各自的数据文件与SSTable文件
-
-
SSTable压缩
-
Tiered Compaction
-
Leveled Compaction
-
参考链接:
- https://docs.scylladb.com/architecture/compaction/compaction-strategies/#compaction-strategies
- https://www.jianshu.com/p/8de55d5df05e
-
-
客户端请求KEY时,先在内存表中查询,没有找磁盘最新段文件,再次新等等
-
如果数据库崩溃,未落盘的数据会丢失,此时需要借助追加式日志(非排序,WAL)恢复
-
写放大:写入一条数据会引起落盘、合并等写操作
-
读放大:在查询一个KEY时会按照内存表->逐级SSTable文件的顺序查询,当查询的KEY不存在,会有较大延迟。
-
缓解方案:Bloom滤波器
- 这里需要指出基础Bloom filter由于Hash映射的有限性,会有误将不存在的元素判定为存在的可能性;另外,对于删除元素操作,bloom filter也无法直接重置标志位。衍生出的变种filter包括:Counting Bloom Filter Partial Bloom Filter Compressed Bloom Filter
-
-
-
-
面向页
B-Tree
-
特点:
- 原地更新
-
让B树更可靠性
- WAL配合(Redo Log),以便在更新页时数据库发生崩溃进行恢复
-
B树优化
-
使用COW,而不是WAL与页面覆盖进行更新操作,即修改的页面写至不同的位置,并创建新的树的父级页指向它完成
-
尽量使得树的页面在磁盘上按顺序存储以加速顺序查找,但随着树的增长,维持该顺序是相当困难的
-
叶子页面添加到兄弟节点的指针
- B+ Tree 非叶子节点只存指向下一级节点的指针;相邻叶子节点间有指针指向
-
-
LSM B-Tree对比
-
LSM优点
- 顺序写SSTable,写入吞吐量高,B树随着树的增大,节点分裂,随机读写的概率会增大
- 压缩得更好,产生的文件较B树更小
-
LSM缺点
- Compaction开销大,查询时延在Compaction时会加大,时延不可控,而B树行为具有更好的预测性
- B树中的键只存在于磁盘上的一个位置,而LSMTREE在磁盘上会有多份数据,B树在事务上有强大语义支持
-
事务处理
面向列
列存储
- Parquet是一种列式存储格式
列压缩
- 如位图BITMAP编码
- 对于稀疏度较高的,还可以用游程编码
列排序
- 排序是针对所有列的,仅对一列作排序无意义
- 排序有助于进行数据压缩,如使用游程编码,但仅对第一排序列有较大压缩效果
写入列存储
- 使用LSM树,如果选用B树,则插入操作需要更新所有的列,而对于LSM树,则可将内容先写入内存,随后落盘进行文件合并。