文章目录

  • 数据存储与检索
    • 数据库核心是数据结构
    • 哈希索引
    • SSTable和LSM-Tree
    • B-trees
    • B-tree和LSM-tree
    • 其他索引结构(*)
    • 事务处理和分析系统
    • 小结

数据存储与检索

本章我们从数据库的角度来探讨探讨如何存储输入的数据,并且在收到查询时找到数据。

针对事务型负载和针对分析型负载的存储引擎优化存在很大的差异。

数据库核心是数据结构

日志通常指的是应用程序的运行输出日志,来记录发生了什么事情。当然日志还有一个更通用的含义,表示一个仅能追加的记录序列集合。它可能是人类不可读的,可能是二进制格式而只能被其他程序读取。

日志方式的查找开销是O(n)O(n)O(n)。

为了高效查找数据库中的特定键的值,需要新的数据结构:索引。索引的基本想法是保留一些额外的元数据,将这些元数据作为路标,帮助定位想要的数据。

索引是基于原始数据派生而来的额外数据结构。很多数据库允许单独添加和删除索引而不改变数据库的内容,以影响查询性能。对于写入,任何类型的索引都会降低写的速度(相比于日志的简单追加文件方式)。

所以适当的索引可以加速读取查询,但每个索引都会降低写速度:这是存储系统中重要的权衡设计。

哈希索引

假设数据存储全部采用追加式文件组成,最简单的索引策略是保存内存中的hash map,把每个键一一映射到数据文件中特定的字节偏移量,这样就可以找到每个值的位置。当查找某个值时,使用hash map来找到文件中的偏移量,即存储位置,然后读取内容。

如果key比较少,但每个key都有大量的写操作,将所有key保存在内存中是可取的。可以采用上述方式。

具体可见日志结构的存储引擎-bitcask。

哈希表索引的缺陷:

  1. 哈希表必须全部放入内存。因为磁盘上的hash map表现不好,需要大量的随机访问I/O,当哈希变满时,继续增长代价昂贵,并且哈希冲突时需要处理复杂的处理逻辑。
  2. 区间查询效率不高,只能采用逐个查找的方式查询每一个键。

SSTable和LSM-Tree

上述的日志结构的存储段中的键值对是按照写入顺序排列的。如果我们希望按照键对键值对排序,这种格式称为SSTable,它有以下优点:

  1. 合并段更加高效简单。
  2. 在文件中查找特定的键时,不需要在内存中保存所有键的索引。(通过稀疏索引减少索引的数量)
  3. 读请求需要扫描全球范围内的多个键值对,可以考虑将这些记录保存到一个块中并且在写磁盘之前将其压缩。

构建和维护SSTables
存储引擎的基本工作流程如下:

  1. 当写入时,将其添加到内存中的平衡树数据结构中(例如红黑树),有时被称作内存表
  2. 当内存表过大时,将其作为SSTable文件写入磁盘。由于树已经维护了按键排序的键值对,写磁盘可以比较高效。新的SSTable文件成为数据库的最新部分。当SSTable写磁盘的同时,写入可以继续添加到一个新的内存表实例
  3. 为了处理读请求,首先尝试在内存表中查找键,然后是最新的磁盘段文件,接下来是次新的磁盘段文件,以此类推,直到找到目标
  4. 后台进程周期性执行段合并和压缩过程,以合并多个段文件,并丢弃那些被覆盖或者删除的值

以上的算法本质在很多引擎使用,如LevelDB,RocksDB,类似的存储引擎还有Cassandra和HBase。

LSM-Tree的基本思想是保存在后台合并的一系列SSTable。基于合并和压缩排序文件原理的存储引擎通常都被称为LSM存储引擎。

B-trees

B-tree同样保留按键排序的键值对,以实现高效的键值查询和区间查询,但是它本质上具有非常不同的设计理念。

不同于之前看到的日志结构索引将数据库分解为可变大小的段,通常大小为几兆字节或者更大,并且始终按照顺序写入段。B-trees将数据库分解成固定大小的块或者页,传统上大小是4KB,页是内部读/写的最小单元。

由于每个页面都可以使用地址进行标识,就可以让一个页面引用另外一个页面。可以用这些页面引用构造一个树状页面,索引一个键时,从根页面开始逐渐向下寻找,直到到达一个包含单个键的叶子页,它包含每个内联键的值或包含可以找到值的页的引用。

分支因子是一个页中包含的子页的引用数量,实际中通常为几百个。

更新策略和崩溃恢复策略:

  1. 更新现有键的值即搜索包含该键的页子叶,更改该页的值
  2. 添加新键,需要找到范围包含该键的页,并且添加。如果此页无可用空间,则分裂成两个半满的页,且更新父页。
  3. 为了崩溃恢复,使用预写日志WAL,所有修改先更新WAL再修改树本身的页。WAL用于将树恢复到最近一致的状态。

B-tree和LSM-tree

根据经验,LSM-tree通常对于写入更快,B-tree读取更快。

LSM-tree的优点:

由于B-tree存储引擎按固定页写入,那么通常每一页都会有些空间无法使用。而LSM-tree不是面向页的,并且定期重写SSTable以消除碎片化,所以具有较低的碎片率。

LSM-tree通常能够承受比B-tree更高的写入吞吐量,部分原因是具有较低的写放大(一次数据写入导致多次磁盘写入称为写放大),部分原因因为它是以顺序方式写入紧凑的SSTable文件。

LSM-tree的缺点:

日志结构存储的缺点是有时候压缩过程会干扰正在进行的读写操作。另外写入吞吐量和压缩要共享磁盘的有限的写入带宽,也就是说数据库的数据量越大,压缩就需要越多的磁盘带宽。

B-tree的每个键恰好唯一对应于索引中的某个位置,而日志结构的存储引擎可能在不同的段中具有相同键的多个副本。如果在这种场景下需要提供强大的事务语义,无疑B-tree更具竞争力。

其他索引结构(*)

在索引中存储值
多列索引
全文搜索和模糊搜索
在内存中保存所有内容

事务处理和分析系统

待补

小结

本章的重点在于介绍数据库内部如何处理存储和检索,例如存储新数据和查询数据。

存储引擎大致分为两大类:针对事务处理(OLTP)优化的架构,以及针对分析型(OLAP)的优化架构。

  1. OLTP系统通常面向用户,这意味着它们可能收到大量的请求。为了处理负载,应用程序通常在每个查询中只涉及少量的记录。应用程序基于某种键来请求记录,而存储引擎使用索引来查找所请求键的数据。磁盘寻道时间通常是瓶颈。
  2. 由于不是直接面对最终用户,数据仓库和类似的分析型系统相对并不太广为人知,它们主要由业务分析师使用。处理的查询请求数目远低于OLTP,但每个查询通常要求很严苛,需要在短时间内扫描数百万条记录。磁盘带宽通常是瓶颈。

在OLTP中分为两个主要流派:

  1. 日志结构流派,只允许追加式更新文件和删除过时的文件,但不会修改已写入的文件。
  2. 原地更新流派,将磁盘视为可以覆盖的一组固定大小的页。B-tree是最典型代表,已用于所有主要的关系数据库和大量的非关系数据库。

数据密集型应用系统设计(3)相关推荐

  1. 数据密集型应用系统设计 [Designing Data-Intensive Applications]

    作者:[美] Martin Kleppmann(马丁·科勒普曼) 著,赵军平 吕云松 耿煜 李三平 译 出版社: 中国电力出版社 出版时间:2018-09-01 数据密集型应用系统设计 [Design ...

  2. Designing Data-Intensive Application《数据密集型应用系统设计》笔记

    Designing Data-Intensive Application 中译<设计数据密集型应用>又名<数据密集型应用系统设计>,我看的是冯若航在gitbook开源的翻译版本 ...

  3. 《数据密集型应用系统设计》读书笔记——第一部分 数据系统基础

    第一部分 数据系统基础 第1章 可靠.可扩展与可维护的应用系统 当今许多新型应用都属于数据密集型,而不是计算密集型.对于这些类型应用,CPU的处理能力往往不是第一限制性因素,关键在于数据量.数据的复杂 ...

  4. 豆瓣评分 9.7 的神书:《数据密集型应用系统设计》

    我最近在读一本好书<数据密集型应用系统设计>(也被叫做 DDIA).这真是本相见恨晚的神书. 这是怎样一本神书?豆瓣评分高达 9.7 分! 什么是「数据密集型应用系统」? 当数据(数据量. ...

  5. 《数据密集型应用系统设计》读书笔记——数据系统基础

    因为个人兴趣,想学学分布式方面的知识,然后找到了这本<数据密集型应用系统设计>,确实非常的不错,无论对于以前的工程还是现在的科研都有启迪和感悟,所以就写份读书笔记记录一下,里面提到的知识非 ...

  6. 数据密集型应用系统设计——笔记

    本篇章内容为阅读<数据密集型应用系统设计>一书的读书笔记. 作为个人成长学习使用,同时希望对刷到的朋友有所帮助,一起加油哦! 生命就像一朵花,要拼尽全力绽放,芳香四溢,在风中舞蹈! 写在前 ...

  7. 数据密集型应用系统设计-第七章分布式系统的麻烦-笔记

    这阵子在看数据密集型应用系统设计书籍,自己把书籍比较重要的内容整理出来,基本一天一更,请感兴趣的朋友多多关注! 整个系列会在这几天都发布出来,可以关注一下 链接: 数据密集型应用系统设计-笔记. 文章 ...

  8. 数据密集型应用系统设计(读书笔记)第一天

    第一章: 可靠.可扩展与可维护的应用系统 数据密集型应用通常也是基于标准模块构建而成,每个模块负责单一的常用功能.例如,许多应用系统都包含以下模块: 数据库:用以存储数据,这样之后应用可以再次面问. ...

  9. 《数据密集型应用系统设计》读书笔记——第二部分 分布式数据系统(二)

    第8章 分布式系统的挑战 故障与部分失效 当你在⼀台计算机上编写一个程序时,它通常会以一种确定的方式运⾏:⽆论是⼯作还是不工作.充满错误的软件可能会让人觉得电脑有时候是"糟糕的一天" ...

  10. 数据密集型应用系统设计--数据分区

    数据分区与数据复制 分区的目的一般是提高可扩展性.容错性和集群吞吐,同一个分区会在多个节点中都有副本. 容错性:一个节点挂掉,则这个节点上的分区,在其他节点上都有副本,可以查询其他的节点 可扩展性:新 ...

最新文章

  1. 在docker中搭建apache Tomcat+JDK环境
  2. 深度学习核心技术精讲100篇(三十二)-网易实时数仓实战应用
  3. C++链表linked list(附完整源码)
  4. android中判断sim卡状态和读取联系人资料的方法
  5. 你需要的git命令大全来了
  6. Struts1.x和Struts2.0的Action的区别
  7. matlab画二维颜色深浅,matlab中如何为二维图形填充渐进的颜色
  8. vagrant开启Xshell使用密码登录方式
  9. 用PHP做服务器接口客户端用http协议POST访问安全性一般怎么做
  10. 《21天学通Java(第7版)》——VC程序员的学习笔记1
  11. java实习鉴定书个人鉴定_大学生实习鉴定表自我鉴定范文
  12. 思科模拟器CIsco Packet Tracer路由器上配置 DHCP
  13. 图解 Cisco IOS 命名规范
  14. looking for domain authoritative name server and domain name location
  15. BBS中用SSH方式登录添加附件
  16. 记一次微信支付回调失败的修复
  17. 【生成对抗网络 论文泛读】……pix2pix pix2pixhd……
  18. 从校训、企业文化到团队文化
  19. C语言完成图书管理系统
  20. Android 耳机驱动知识

热门文章

  1. C++强制关闭进程的办法
  2. 查询至少生产两种不同的计算机(PC或便携式电脑)且机器速度至少为133的厂商
  3. 在linux中 系统默认,在Red Hat Linux 9中,系统默认的( )用户对整个系统拥有完全的控制权...
  4. conceptd什么时候上市_iPhone12 Pro Max什么时候上市售价
  5. 虹软android工程师,虹软人脸识别技术公开课开讲!AI工程师如何快速进阶
  6. html5 canvas 图片拼接,HTML5 canvas drawImage方法实现读取图片数据截图拼接图片。
  7. 数据库主键如何设计?
  8. 详解JavaScript创建对象——构造函数模式
  9. 128*64点阵图形液晶显示屏程序设计教程
  10. 国家电网计算机知识点归纳,国家电网考试知识点整理.doc