数据存储与检索

如果你把东西整理得井井有条,下次就不用再找了。

        ——德国谚语

从最基本的层面看,数据库只需要做两件事情:向它插入数据时,它就保存数据;之后查询时,它应该返回那些数据

数据库核心:数据结构

许多数据库都使用日志(log),日志是一个仅支持追加式更新的数据文件;实现原理大致为:每行包含一个key-value对,用逗号分割,每次调用插入时,追加新内容到文件末尾,因此多次更新某个键时,旧版本的值不会被覆盖,而是需要查看文件中最后一次出新的键来查找最新的值

索引是基于原始数据派生而来的额外数据结构。很多数据库允许单独添加和删除索引,而不影响数据库的内容,它只会影响查询性能。维护额外结构势必会引入开销,特别是在心数据写入时,。对于写入,它很难超过简单地最佳文件方式的性能,因为那已经是最简单的写操作了。由于每次写数据,需要更新索引,因此任何类型的索引通常都会降低写的速度

哈希索引

key-value类型并不是唯一可以索引的数据,但随处可见,而且是其他更复杂索引的基础构造模块

那么最简单的索引策略是:保存内存中的hash map,将每个键一一映射到数据文件中的特定字节偏移量,这样就可以找到每个值的位置;每当在文件中追加新的数据时,还要更新hash map来反应刚刚写入数据的偏移量(包括插入和更新)。当查找某个值时,使用hash map来找到文件中的偏移量,即存储位置,然后读取

把数据追加到文件中,怎么避免用尽磁盘空间?可以将日志分解为一定大小的段,当文件达到一定大小时就关闭它,并将后续写入新的段文件总,然后在这些段中执行压缩。压缩意味着在日志总丢弃重复的键,只保留每个键最近的更新;此外压缩往往使得段更小,也可以在压缩的同时将多个段合并在一起

实现过程中需要考虑的问题

  • 文件格式:CSV不是日志的最佳格式,更快更简单的方法是使用二进制格式,首先以字节单位来记录字符串长度,之后跟上原始字符串(不需要转义)
  • 删除记录:如果需要删除键和它关联的值,则必须在数据文件中追加一个特殊的删除记录(有时候称为墓碑),当合并日志段时,一旦发小墓碑标记,则会丢弃这个已删除键的所有值
  • 崩溃恢复:如果数据库重新启动,则会丢失内存中的hash map。原则上,可以通过从头读取整个段文件,然后记录每个键的最新值得偏移量;但是如果段文件很大,这将使服务器重启变慢。Bitcask通过将每个段的hash map的快照存储在磁盘上,可以更快地加载到内存中
  • 部分写入记录:数据库随时可能崩溃,包括将记录追加到日志的过程中。Bitcask文件包括校验值,这样可以发现损坏的部分,并丢失
  • 并发控制:只有一个写线程,允许多个读线程

为什么不原地更新文件:

  • 追加和分段合并主要是顺序写,它通常比随机写入快得多,特别是在旋转式磁盘中。在某种程度上顺序写入在基于内存的固态硬盘中也是适合的
  • 如果段文件是追加或者不可变得,则并发和崩溃恢复要简单的多
  • 合并旧段可以避免随着时间的推移数据文件出现碎片化的问题

哈希表索引的局限性:

  • 哈希表必须全部放入内存,原则上,可以在磁盘上维护hash map,但很难使磁盘上的hash map表现良好,它需要大量的磁盘I/O,当哈希变满时,继续增长代价昂贵,并且哈希冲突时需要复杂的处理逻辑
  • 区间查询效率不高。例如:不能简单的支持扫描kitty00000和kitty99999区间内的所有键,只能采用逐个查找的方式,查询每一个键

SSTables和LSM-Tree

SSTable:与哈希索引相比,要求key-value对的顺序按键排序,要求每个键在每个合并的段文件中只能出现一次(在压缩的过程中已经确保了)

SSTable相较于哈希索引的优点

  1. 合并段更加简单高效,即使文件大于内存。方法类似于合并排序算法中使用的方法:比较每个文件的第一个键,把最小的键(按照排序顺序)拷贝到输出文件,并重复这个过程,这会产生一个新的按键排序的合并段文件。如果相同的键出现在多个输入段怎么办?记住!每个段包含在某段时间内写入数据库的所有值。这意味着一个段文件中的所有值肯定比其他段中的所有值更新。当多个段包含相同的键时,可以保留最新段的值,并丢弃旧段的值
  2. 在文件中查找特定的键时,不需要再内存中保存所有键的索引;因为键是有序的,可以根据排序规则确定键的大致位置,然后扫描查询;所以仍然需要一个内存索引来记录某些键的偏移,但它可以是稀疏的,由于可以很快的扫描几千字节,对于段文件中的几千字节,只需要一个键就足够了
  3. 由于读请求往往需要扫描请求范围内多个key-value对,可以考录将这些记录保存到一个块中,并在写磁盘之前将其压缩&#
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值