CMU 15-445 数据库课程第五课文字版 - 缓冲池(下)

简介: CMU 15-445 数据库课程第五课文字版 - 缓冲池(下)

最后一个优化是绕过缓冲池(buffer pool bypass)


image.png


对于顺序扫描运算符,它要扫描每一页,但是这些页仅仅一次扫描之后就立刻用不到了,如果都加载到缓冲池的话,会严重影响执行效率,并且污染缓冲池。

在 Informix 这个系统中叫做轻量扫描(Light Scans)。并且 Oracle,SQLServer,PostgresSQL 中也有这种优化机制。

下一个我们要讲的是,如果缓冲池满了,在缓冲池中替换页的不同策略,在此之前,我们先来看下操作系统中的机制:


image.png


我们要执行的大多数磁盘操作都是通过操作系统提供的 api,我们讲过mmap()或者read()和write(),对于这些 api 除非你明确指定其中的参数告诉操作系统,否则操作系统会维护自己的文件系统缓存,它通常被称为页面缓存(Page Cache)。简单来说:当你请求从磁盘读取一个页面,如果它还没有加载,就从磁盘中获取它加载到页面缓存中,然后返回一个指向你的页面的指针,之后你必须从操作系统页面缓存复制到用户空间。所以你会有一个多余的复制,一个存储在操作系统页面缓存中,一个存储在你实现的缓冲池中,所以大多数 DBMS 所做的是使用 O_DIRECT 标志来绕过操作系统的页面缓存。


image.png


我们可以采用不同的策略来确定当缓冲池填满时,我们需要腾出一个帧,以便插入一个新页。我们如何决定从缓冲池中删除哪些页呢?我们要考虑不同的方面:

  • 正确性(Correctness):我们不想有任何数据被破坏的问题,例如,扔掉我们没有正确地写出的脏页。
  • 准确性(Correctness):即查询结果是查询想要查的数据
  • 速度(Speed):缓冲池过期需要保证查询速度,也需要考虑能快速决定哪些帧被替换,如果你花了所有的时间思考去掉哪个页最合适,那么你花在这上面的时间可能比你从智能算法中得到的好处还要
  • 元数据大小(MetaData):我们需要担心的是为了进行页删除,我们存储了多少元数据,不能太多


image.png


这是最简单的一种算法,LRU(Least Recently Used,最近最少使用策略),它在很多不同的系统领域被使用。简单的实现方式是为每个页面维护一个时间戳,记录它最后一次被查询访问的时间。当 DBMS 需要删除一个页时,这很简单,我们只需要找到时间戳最早的页面,也就是最近访问最少的页面

这是一种通用的依赖于你最近使用过的页,你最近访问过的页,很快就会再次被使用这个假设的算法。


image.png


另一个策略是时钟策略(Clock Policy),和 LRU 有点不同,这也是经常被用到的一种策略。它的实现方式通常是在每页上分配一个标记位,这个引用位可以是 0 或者 1。如果这个页面被访问到了,就会标记为 1。我们有一个时针会不断的扫描每一页,如果时钟扫描的这一页标记位为 1,那么就会更新为 0,如果本来就是 0 了,就会把这个页面过期掉。过这个算法给你带来的好处是不用维护一个完整的时间戳(每页占用4个字节或者8个字节),这个算法每页只需要一个比特标记位,所以空间的消耗会小很多


image.png


LRU 以及时钟策略都有一些问题,它们很容易受到连续洪流(Sequential Flooding)的影响。就像前面提到的,你要做的主要假设是你最近使用过的页,你最近访问过的页,很快就会再次被使用。这对于倾斜的访问模式很好,但是如果查询执行顺序扫描,需要读取每个页,会造成只读一次然后就再也不会看的页污染缓冲池。


image.png


你可以使用一些更好的策略,例如LRU-K,它不是跟踪某件东西是否被访问,也不是跟踪某件东西最近被访问的时间戳,你要看最后 K 次引用的历史。假设 K 现在是 2,即你记录了最近当某东西被访问时的两个时间戳,然后你就可以计算出以后访问的间隔。如果这个间隔时间比较长,那么就不能经常使用,我们可以把它扔掉。如果间隔时间短得多,证明它经常被访问*,我们可能会想保留它。

同时,你还可以做更高级的优化,例如:根据算法我们算出这页平均访问间隔大概是10分钟左右,你可以期望10分钟后,我需要这个页,这样你可以做一些更智能的预取

但是,这个算法也会带来更多的元数据开销,这是我们需要权衡的。


image.png


另一种选择是使用一些本地化的策略,即以某个查询或者事务的基础决定缓冲池的过期策略,例如 Postgres 就在每个查询或事务的级别维护一个独立的唤醒缓冲池,


image.png


另一个更好的策略可能是根据不同的访问模式提供优先级提示(Priority Hints),例如,DBMS 知道访问索引和顺序扫描的访问模式的区别,因此,您可以向缓冲池提供一些提示说明哪些页面是重要的,哪些页面是我们可能不关心的。

举个例子,假设我们正在插入一些连续的 id,因为这些值是单调递增的,所以它们总是会被插入到树的右边;如果你想要执行一次扫描,你的访问路径可能会不同,但它们有一个共同点就是你总是从这个根页开始。你可以向缓冲池管理器提供的一个提示是,缓冲池保留这个根页,这两种类型的查询都需要它。


image.png



如果你的缓冲池中有一个不脏的页面,当它需要从缓冲池中剔除的时候,你可以直接删除它,覆盖它,我们不需要保留它。因为没有任何变化,它备份在磁盘上,如果我们需要我们总是可以从磁盘恢复它。但是如果是脏页的话,你需要将脏页的更新写回磁盘以保证更新的持久化。

在快速缓冲页驱除和持久写脏页之间有一种权衡。


image.png


为了减少持久化脏页的时候带来的写磁盘的 I/O 阻塞,一般会有一个后台写过程(Background writing process)。DBMS可以定期遍历页表并将脏页写入磁盘。


image.png


除了元组和索引缓冲池之外 DBMS 还需要内存来管理其他东西,包括:

  • 排序与连接缓冲
  • 查询缓存
  • 维护缓冲
  • 日志缓冲
  • 词典缓冲

这些元素有些可能有底层持久化到磁盘的元素,有些只存在于内存中,我们在后面的课程可能也会涉及到。

相关文章
|
3月前
|
SQL 关系型数据库 MySQL
学成在线笔记+踩坑(3)——【内容模块】课程分类查询、课程增改删、课程计划增删改查,统一异常处理+JSR303校验
课程分类查询、课程新增、统一异常处理、统一封装结果类、JSR303校验、修改课程、查询课程计划、新增/修改课程计划
学成在线笔记+踩坑(3)——【内容模块】课程分类查询、课程增改删、课程计划增删改查,统一异常处理+JSR303校验
|
3月前
|
前端开发 应用服务中间件 API
|
5月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的《数据库原理及应用》课程平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的《数据库原理及应用》课程平台的详细设计和实现(源码+lw+部署文档+讲解等)
|
6月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue的数据库课程在线教学的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的数据库课程在线教学的详细设计和实现(源码+lw+部署文档+讲解等)
60 2
|
6月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue的《数据库原理及应用》课程平台的详细设计和实现
基于SpringBoot+Vue的《数据库原理及应用》课程平台的详细设计和实现
38 1
|
6月前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的数据库课程在线教学附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的数据库课程在线教学附带文章和源代码部署视频讲解等
48 4
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的《数据库原理及应用》课程平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的《数据库原理及应用》课程平台附带文章源码部署视频讲解等
50 0
|
7天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
27天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
34 1
|
29天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
39 4