《数据密集型应用系统设计》读书笔记--第三章

数据存储与检索

数据结构:

日志是仅支持追加式更新的数据文件。

为了避免查找时从头到尾扫描文件,采用索引结构。

索引:

一、Hash索引

保存内存中的hash map,把每个键一一映射到数据文件中字节偏移量。更新键和插入键时要更新hash map。适合每个键的值频繁更新的场景。

节省空间的方法:压缩段+合并段

当文件达到一定大小时,关闭文件的写入,将新的数据写在新的段上。在已关闭的段上执行压缩,丢弃重复的键,之保留最新的更新。

对关闭写入的段执行合并,合并的段会写入新的文件中。在合并的过程中数据的访问仍然在旧的文件上,合并成功以后,在新的文件上访问。

每个段有自己的Hash表。查找数据时找key,从最新的段的hash表开始找起。

细节问题:

1.删除记录:需要删除一对键值时,在日志文件中追加一个删除记录(墓碑),当合并时如果发现墓碑记录则丢弃这个记录。

2.崩溃恢复:当hash表丢失时避免从头扫描文件重建hash表,会保存每个段的hash表快照到磁盘上。

3.损坏的记录:写的过程中如果发生数据库崩溃,Bitcask文件包含校验值会发现损坏部分并且丢弃。

4.并发控制:写线程一个,读线程多个。

追加式的写入方式优点

1.在磁盘上顺序写速度是最快的。

2.段文件时不可变的,写入时如果发生崩溃,避免出现文件中新值和旧值混杂的情况。

3.合并操作避免出现碎片化的问题。

Hash索引的局限性:

Hash表必须全部放入内存。区间查询效率不高,必须从头遍历所有键值(因为未排序)。

2. SSTable->LSMTree

段文件中key有序,称为排序字符串表。合并时类似于merge排序。

优点

1.合并简单高效。

2.不需要在内存中保留所有键的索引(保存一个稀疏的索引表即可)。可以按已知键和偏移量在一个范围中找。

3.可以将多条记录按块保存,索引指向块的开头。

写入流程(修改数据相当于写入新值,旧值不会被访问到了):

1.写入时,把数据添加到内存中的平衡树数据结构当中(红黑树)(此树称为内存表)。同时把数据也写进磁盘日志。日志不需要按照key值排序,只用于数据库崩溃以后的恢复。

2.当内存表大于阈值时,所为SSTable文件写入磁盘。此时新写入的数据写到新的内存表中。

读过程:先尝试在内存表中找键,如果找不到到最新的SSTable中找键。以此类推。(读不存在的key时候效率会比较低,用布隆过滤器优化)

后台:周期性合并和压缩SSTable。

LSMTree:基于合并和压缩排序文件原理的存储引擎通常被称为LSM存储引擎。

二、B-Trees

B-Tree是最广泛使用的索引结构。

日志索引结构将数据库分解为可变大小的段,B-Tree将数据库分解成固定大小的页。页是内部读写的最小单元。页用地址(磁盘地址)标识。

某一页被指定为B-Tree的根。根包含了若干对<key-子页的引用>,每个子页包含一定范围内的键和引用。一个页包含的子页引用数量称为分支因子

在底层的写操作是覆盖旧页。

崩溃恢复方法:B-Tree修改必须先写日志再修改树本身。

对比LSM-Tree和B-Tree

1.LSM-Tree写放大更低,因为以顺序方式写入SSTable而不是重写树中多个页。

2.LSM-Tree磁盘上文件比B-tree小,因为B-Tree页中某些空间无法使用。LSM-Tree会通过合并减少碎片。

3.日志结构的缺点是压缩占用磁盘有限的并发资源和带宽,会导致读写请求等待,压缩速度和写入速度不匹配等问题。

4.

三、事务处理与分析处理

事务:组成一个逻辑单元的一组读写操作。

OLTP:联机事务处理。是传统关系型数据库的主要应用,用来执行一些基本的、日常的事务处理,比如数据库记录的增、删、改、查等等。

OLAP:对实时性要求不高,但处理的数据量大,通常应用于复杂的动态报表系统上。

数据仓库:用于分析目的的单独的数据库。针对分析访问模式**进行优化。

星型模式:事实表(按时间发生的事件)位于中间,周围围绕着维度表。

 

列式存储:行式存储适合的场景:频繁增删改查,每次都会对一条数据的所有属性读取。但读取大量数据但只分析少数属性的场景时,还需要把每条数据都读到内存。列式存储把每列单独保存为一个文件,每个文件以相同的顺序保存数据行,便于组装成行。

列压缩:往往,列中不同值的数量小于行数。每个2不同的值可以转换为一张位图,每一位表示这一位对应的行有没有这个值。

posted @ 2019-08-07 20:32  pibaba  阅读(533)  评论(0编辑  收藏  举报