DDIA(数据密集型应用系统设计) 读书笔记-第三章

271 阅读4分钟

image.png 本章承接上一章节(数据模型的介绍)进行展开,讲的是存储引擎相关的处理逻辑(数据模型在数据库层面的处理)。

存储引擎

面向日志的存储引擎

哈希索引在面向日志的存储引擎中,维护的key与value在存储对象上的指针偏移量。

Bitcask

是早期的一个日志存储引擎,后面的SSTables以及LSM-Tree都是在它基础上进行相关的优化。但基本的逻辑处理思路还是一样。

image.png

保留一个内存中的哈希映射,其中每个键都映射到一个数据文件中的字节偏移量,指明了可以找到对应值的位置。写是追加写,这样效率高。但由于是追加写,磁盘空间会耗尽,需要进行数据的合并,因为追加写会导致有大量的重复key存在,需要进行合并,key保留最新的value(合并策略是可以调整的),合并过程中,旧的数据还会保留,合并完成后更新原有的哈希内存映射,使之访问新的数据。删除记录,由于数据量大的情况下,删除记录代价较大,需要更新内存和磁盘,可以设置一个附加的删除记录,当查询或者合并时候在删除记录里对比下。崩溃重启,这个时候内存映射全部丢掉,启动过程中需要重新读取全部数据建立内存映射,那么代价会比较大,提前存储内存的哈希映射。并发控制,由于是追加写,只能允许同一时刻一个线程写入。

看这个图,缺点其实是很明显的

  • 哈希映射全部存入内存。内存占有率高
  • 范围查询效率不高,需要在映射中一一查找

SSTables & LSM-Tree

SSTables是在Bitcask的基础上做了相关的优化。

  • 对key排序
  • 存储分为多段,段内部排序
  • 每个key在段内只出现一次

image.png

  • 同时内存中将不需要保存全部的key与偏移量的映射,只需要保存每个段的段首偏移量即可。

image.png 对于key的排序进一步可以利用红黑树或avl树等。这样SSTables就演化成了LSM-Tree. 那么整个流程就变成了这样子。

文件内容和key先写入内存,在内存中进行合并,当达到一个阈值后,追加写到磁盘里,同时key写入到内存树结构中,顺序读取顺序写入的速率将会非常高,同时每次写入都会计入到一个单独日志里,崩溃时候,可以通过这个日志进行恢复。内存中的树结构当达到一定阈值,也会被写到磁盘上。随即读取时候,会优先尝试在内存中找到key,然后会在最近磁盘断种。

面向页的存储引擎

能应用的索引种类较多,聚集索引,非聚集索引 ,联合索引,全文索引,模糊索引等等

B-Tree

B树将数据库分解成固定大小的块或页面,传统上大小为4KB(有时会更大),并且一次只能读取或写入一个页面。这种设计更接近于底层硬件,因为磁盘也被安排在固定大小的块中。

更新操作,会读取所在页,更改完成后,将页写回磁盘。mysql是先写到内存里

新增操作,如果页空间不够时,会引起页分裂(分裂成两个半满页)。mysql用B+树做到了顺序写

崩溃恢复,会有一个redolog,记录所有的操作。mysql写入redolog和页会做事务关联

并发控制,多个写入操作时,需要加轻量级锁

数据处理

这一小节,主要介绍了OLTP和OLAP的区别。

OLTP是在我们传统意义上的数据库进行相关业务的应用。侧重点在于查询返回少量数据,低延迟的写入,同时数据规模在TB以下。比如web应用服务就是OLTP

OLAP是大数据分析业务的应用。需要建立相关数仓,同时这种操作的侧重点在于查询返回大量的数据,数据写入依靠数据流,数据规模咋TB以上。

image.png

列式存储

列式存储主要是针对在数仓中查询事实表时,只查询个别列,但数据记录却有万亿级,导致查询数据量巨大,影响正常业务分析。同时大量的顺序查找,导致索引的作用减少了,这个时候需要的是数据紧凑形式存储,减少磁盘读取次数。基于以上场景,那么列式存储有以下特点:

数据以列方式存储,key-value形式

列的每个数据与其他对应列的数据是有关联关系,能形成一行的关联

列数据非常适合bitmap压缩

写入方案才去的LSM-Tree的方式