DDIA读书笔记 3 数据存储与检索

3 数据存储与检索

3.1 数据库核心:数据结构

3.1.1 哈希索引

  • hashmap存放在内存中,把每个键一一映射到数据文件中特定的字节偏移量,也就是保存每个值在磁盘中的位置
  • 采用日志的方法,把key,value追加到文件末尾。对于删除的记录,可以使用特殊标记。
  • 定期将日志分解成多个小文件(日志段),并使用后台线程对小文件进行合并压缩
  • 缺点
    • 哈希表必须全部放入内存
    • 区间查询效率不高

3.1.2 SSTables和LSM-Tree

  • SSTables:要求哈希表中的key-value对的顺序按键排序

  • SSTables相比哈希索引的日志段具有的优点:

    • 因为每个段内的键是有序的,因此合并多个段内的key-value更高效。(段内有序,并且以最新的段内的键值对为准)
    • 查找某个键值对也更高效
  • 构建和维护SSTables:

    • 使用红黑树或AVL树等内存排序数据结构维护key-value的有序性
    • 基本工作流程:
      • 写入时,将其添加到内存中的平衡数据结构(如红黑树,跳表)中,也称为内存表
      • 当内存表大于某个阈值时,将其作为SSTables文件写入磁盘。新的SSTable文件作为数据库的最新部分。当这个SSTable写磁盘时,写入可以继续添加到一个新创建的内存表中
      • 读取时,首先在内存表中查找,然后找最新的日志段文件,然后找次新的,以此类推
      • 后台进程周期性地执行段合并与压缩,合并多个段文件,并丢弃那些已经被覆盖或删除的值
  • 如何避免数据库崩溃时,在内存中的内存表数据丢失?

    • 在磁盘上保留单独的日志,每个写入立即追加到该日志,该日志无需按键排序,用于在崩溃后恢复内存表。每当将内存表写入SSTables时,这个备份日志文件中相应的日志可以删除
  • 相关产品:LevelDB,RocksDB,Cassandra和HBase

  • LSM存储引擎(Log-Structured Merge-Tree):基于合并和压缩排序文件原理的存储引擎

  • LSM补充

    • https://www.jianshu.com/p/5c846e205f5f
    • https://www.bilibili.com/video/BV1Zz4y1r7BJ
    • https://www.cnblogs.com/fxjwind/archive/2012/08/14/2638371.html
  • Lucene中,从词条到posting list的映射关系保存在类SSTable的排序文件中,这些文件在后台合并

  • 性能优化方法:

    • 查找某个不存在的键时,LSM需要从内存一直找到最旧的段文件,此时使用布隆过滤器快速判断某个键不存在。
    • SSTables大小分级和分层压缩策略

3.1.3 B树

  • B树将数据库分解成固定大小的块或页,页是内部读写的最小单元。页之间可以相互应用,通过磁盘地址,而不是内存。页组织成多叉树的形式。
  • B树有如下特点(补充):
    • 所有键值分布在整颗树中(索引值和具体data都在每个节点里);
    • 任何一个关键字出现且只出现在一个结点中;
    • 搜索有可能在非叶子结点结束(最好情况O(1)就能找到数据);
    • 在关键字全集内做一次查找,性能逼近二分查找;
  • 可靠性:
    • 每个B树的修改必须先更新WAL(write-ahead log)预写日志,然后再修改树本身的页。当数据库在崩溃后需要回复时,该日志用于将B树回复到最近一致的状态。
  • 优化B树:
    • 写时复制->并发控制
    • 进一步压缩键,节省页空间
    • 相邻子页按顺序保存在磁盘
    • 同级兄弟节点之间相互引用

3.1.4 B+树和B树(补充)

  • B+树改进了B树,内部节点不存数据,只存指向子页节点的引用,这样每个内部节点可以指向更多的子页,树的高度能进一步压缩,磁盘IO更少,检索时间更短
  • 数据存放在叶子节点,叶子节点间以链表形式,更高效地支持范围查询

3.1.5 B树和LSM树的对比

  • LSM树写入更快,B树读取更快。
  • LSM树属于日志结构流派,只运行追加式更新文件,不会修改文件。B树属于原地更新流派
  • LSM树的优点
    • 磁盘顺序写,比B树随机写要快
    • 支持更好地压缩。B树中的页存在碎片。LSM树定期重写SSTables以消除碎片
  • LSM树的缺点
    • 压缩操作可能影响读写操作,包括占用磁盘IO,这时真正的读写操作需要等待
    • 要衡量好压缩操作和读写操作占用磁盘带宽的比例。如果压缩操作占用磁盘带宽少,就可能导致磁盘上未合并段的数量不断增加,影响读性能,甚至导致磁盘空间不足。
    • LSM可能在不同的段中具有相同键的多个副本,B树则只有一个。

3.1.6 其他索引结构

  • 索引的键是查询的对象,值可以是以下两种:
    • 值的实际内容
    • 值的地址引用,这种情况下边,存储行的具体位置称为堆文件
  • 聚集索引和非聚集索引
    • InnoDB中主键都是聚集索引,二级索引引用主键的位置
    • 覆盖索引:在索引中保存一些表的列值,无需回表操作,就支持只通过索引即可得到某些查询的结果(这种情况下,称索引覆盖了查询)
  • 多列索引
  • 全文搜索和模糊索引
    • Lucene能够在某个编辑距离内搜索文本
  • 内存数据库

3.2 OLTP和OLAP

  • OLTP和OLAP的特征对比
    在这里插入图片描述

  • SQL能用于OLTP和OLAP,但如今的趋势是,放弃使用OLTP系统用于分析目的,而是在单独的数据库上运行分析,即数据仓库

    • 在OLTP上执行临时分析查询,代价高,通常需要扫描大量数据,会损害并发执行事务的性能
    • OLTP机制不适合数据仓库,OLAP需要在大量行中顺序扫描,索引的有效性显著降低,此时最重要的是紧凑编码数据,减少磁盘读取的数据量。
    • 从OLTP导入数据到数据仓库(ETL,Extract-Transform-Load)
    • 数据仓库针对分析访问模式进行优化

    image-20210111182633833
    在这里插入图片描述

  • OLAP产品:Teradata、SAP HAHA等,基于Hadoop的SQL项目如Hive,Spark SQL、Facebook Presto、Apache Tajo和Apache Drill等

  • 星型与雪花型OLAP模式

    • 事实表和维度表。事实表位于中心,引用维度表。
  • 数据仓库表通常非常宽

3.3 列式存储

3.3.1 目的

  • 数据仓库的事实表中列数量多,通常超过100列
  • 数据仓库很少执行select *操作,而是select指定的某几列
  • 面向行的存储:数据按行存储,读取出整行数据,再解析过滤出所需的列
  • 面向列的存储:数据按列存储,查询只需要读取和解析某些列,可以节省大量工作

3.3.2 列压缩

  • 面向列的存储更适合压缩
  • 如果列中不同值的数量小于行数,可以使用位图编码

3.3.3 列存储中的排序

3.3.4 列存储的写操作

  • 面向列的存储、压缩和排序有助于加速读取,但导致写入困难
  • 参考LSM树,新插入的数据,首先写入内存存取去,累计到足够数量时写入磁盘,与磁盘上的列文件合并。

3.3.5 聚合:数据立方体与物化视图

  • 对于聚合操作结果的缓存
    • 物化视图
    • 数据立方体

、压缩和排序有助于加速读取,但导致写入困难

  • 参考LSM树,新插入的数据,首先写入内存存取去,累计到足够数量时写入磁盘,与磁盘上的列文件合并。

3.3.5 聚合:数据立方体与物化视图

  • 对于聚合操作结果的缓存
    • 物化视图
    • 数据立方体
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值