cmu15-445笔记三 缓存池

存储-2

How the DBMS manages its memory and move data back-and-forth from disk.

DBMS是怎么管理其内存的,怎么与硬盘交互的(包括加载和写数据)。

本节课主要介绍缓存池的加载策略、替换策略。

Buffer Pool Manager

缓存池存在于内存中,用于缓存磁盘中的数据库文件的部分页。

缓存池有两大作用,

  1. 缓存页访问,因为用户有可能再次访问该页,这样的话就可以直接去内存中查询,提升效率;
  2. 缓存页更新,用户对数据库的内容的修改也是先被存储在内存的缓存池里的,先把修改缓存在内存中,再集中将修改写回硬盘或者采用其他策略,而不是每次一修改就立刻写回硬盘。

两大控制:

  1. 空间控制:经常使用的页靠近一起
  2. 时间控制:决定何时读数据页、何时写回、替换,最小化磁盘IO时间

数据查找的基本流程

DBMS的执行引擎会先去缓存池中找,看看2号页是否已经被缓存在其中,如果没有的话,就从硬盘中把索引页读到缓存池里,通过索引页得知我们想要的2号页在硬盘中的位置,然后去硬盘中再把2号页读入缓存池,之后把缓存池中2号页的指针返回给执行引擎。

缓存池基本模型

缓存池由数组形式的连续存放的一些帧构成,每个帧用于缓存数据库文件的一个页。

对于缓存池的查找同样可以使用索引加快,PageTable就追踪了页在缓存池中的情况。

一段辨析:

  • page directory:映射了 page id to page location
  • page table:映射了 page id to page frame in buffer pool

一些策略:

  • 全局策略:为所有活跃事务统一安排
  • 局部策略:为每个事务单独管理

缓存池的性能优化策略

(1)多缓存池

数据库有各种各样的页,可以为每种类型的页创建缓冲池;可以为不同的database建立缓冲池;

多个缓冲池可以减少锁争用。具体实现上,可以采用数据ID到缓冲池的映射记录,也可以采取哈希方式。

(2)预拉取 prefetch

执行全表扫描时,可以预先将未来读取的数据页从磁盘中读入内存。

(3)共享扫描 scan sharing

If a query wants to scan a table and another query is already doing this, then the DBMS will attach the second query’s cursor to the existing cursor.

两次查询共享一次执行结果。

(4)Buffer Pool Bypass

旁路扫描,又名“轻扫描”。有些数据我们可能只需要用一次,后面也不会用了,我们可以将这种数据直接从磁盘放入内存当中没有池化的区域,之后把这块内存交给执行引擎使用,执行引擎使用完之后就把这块内存释放或者垃圾回收。

比如全表扫描的连续读,每张数据页只用一次,若不用轻扫描,将出现大量的页置换。

(5)OS cache

操作系统自己也实现了页缓存。但是DBMS一般会绕过操作系统提供的缓存机制,不需要操作系统缓存数据库文件,因为和DBMS维护的缓存池相比,操作系统对自己提供的磁盘缓存区没有很明确的淘汰策略,即每个缓存块保留多久,何时淘汰,甚至可以说OS的页缓存的淘汰机制很差,并且OS提供的缓存的DBMS的缓存池如果都存储了同样的数据,那就是很大的冗余(redundant)。

因此DBMS需要读磁盘时,在操作系统提供的磁盘读写api中加入O_DIRECT参数,直接和磁盘进行I/O,绕过操作系统的页缓存。

Replacement Policies

DBMS的缓存池替换策略要保证它的正确性(不能把正在使用的页踢出),准确性,速度(不能花费太长时间用于决定踢出哪一页,即相关置换算法的复杂度不能太高),并且注意维护元数据带来的开销(比如说,元数据记录的是哪个页在缓存池里,哪个页不在缓存池里,把一些页踢出之后,要更新元数据,更新元数据的时候也不宜有太大开销)

LRU

(1)原理

Least Recently Used,最近最久未使用。使用一个最近使用时间降序的有序队列,优先清理队列最后的数据。

(2)实现

一种实现方法,给缓存池中的每个页带上时间戳。每次牺牲页时,找出时间戳最小的页。可想而知,查询时间复杂度O(N)。可以采取排序的方法优化,保持队头的时间戳最小。

另一种方法,采用环形队列的近似估计。缓存池中的页以逻辑方式形成环形,页带有访问标志ref。时钟指针顺时针旋转,如果遇到页的ref=1,则重置ref=0,然后转到下一个。

环形队列这个没搞懂

(3)缺点:缓存污染问题

面对大量一次性的扫描时,热点数据将被驱逐。比如以下例子:

1
2
3
Q1 SELECT * FROM A WHERE id = 1 
Q2 SELECT AVG(val) FROM A
Q3 SELECT * FROM A WHERE id = 1
1
偶发性的、周期性的批量操作会导致LRU命中率急剧下降,这时候缓存中的数据大部分都不是热点数据。

LRU-K

论文指路:https://dl.acm.org/doi/epdf/10.1145/170036.170081

(1)原理

核心概念:Backward K-distance ,Backward k-distance is computed as the difference in time between current timestamp and the timestamp of kth previous access。

我们有磁盘页的集合$N={1,2,3,..,n}$,然后给定磁盘页访问的时间序列 $r_1, r_2,…r_t$,其中$r_t = p$表示在t时刻访问页号为p的磁盘页,那么页号p的Backward K-distance 可以表示为 $b_t(p, K)$。

$b_t(p, K) = x$ ,如果 $r_{t-x}=p$,并且在时刻t-x到t中,p出现了K次。

$b_t(p, K) = +\infin$ , 如果在 1,2,3..t 时刻中,p出现不足K次。

LRU-K算法就是在驱逐页面时,选择具有最大Backward K-distance的页。如果有多个页的Backward K-distance都是正无穷,那么可采取其他页面替换算法,比如LRU算法,驱逐最近不常使用的页面。

(2)实现

在实现上会维护两个队列historybuffer。histroty队列存储访问次数未到达K次的页号,buffer队列存储访问次数达到K次的页。

历史队列可以采取多种驱逐算法,比如FIFO、LRU、LFU。根据不同驱逐算法,历史队列也有不同维护方式。采取FIFO时,历史队列直接采用先进先出方式;采用LRU时,可以维护一个有序链表。链表的顺序由访问时间决定,表头最近使用,表尾最久使用。访问链表某个节点时,将该节点调整到表头。驱逐页面时从表尾开始。

缓冲队列根据Backward k-distance排序,在驱逐页面时,选择最大Backward K-distance的页。访问一个页面,更新其Backward K-distance同时也需要调整其位置。

查找页的过程:为了达成O(1)的查询,还需维护一个哈希表,记录页号对应的地址。

插入页的过程:首先查找页在缓冲队列中还是历史队列中。队列未满可以按照队列规则插入,队列满时按照队列驱逐规则牺牲页面,然后再按队列规则插入。

注意:还需要一个容器access_history,记录每个页面last K 次的时间戳。

(3)K值确定

1
K值增大,命中率会更高,但是适应性差(清除一个缓存需要大量的数据访问,一般选择LRU-2)。

Localization

The DBMS chooses which pages to evict on a per txn/query basis. This minimizes the pollution of the buffer pool from each query.

本地化:有点抽象,像是为每个事务单独维护一个驱逐页面的需求,使得各个事务互不影响。

PRIORITY HINTS

优先级提醒:DBMS执行引擎在运行时可以给缓存池一些指示,类似于“告诉缓存池这个页很重要,后面还要被用到,不要轻易清理”,至于怎么判断出来某个页重不重要,可以通过机器学习算法或者其他的很高级的策略来实现。

Dirty Page

脏页说的就是在内存里面被修改了但还没写回磁盘的页。干净的页可以直接丢弃,但脏页必须刷回磁盘作持久化。

脏页的存在催生了WAL策略,即write ahead log,修改缓存池的数据之后不会立刻写回磁盘,否则会导致过多的磁盘I/O开销。一般会找一个机会集中写回,但是如果修改了缓存池里的数据后断电了,为了解决这个问题,可以额外再记个日志,专门记录哪些东西在缓存池里被修改了但还没写回磁盘,我们可以在用户修改数据库时,不将缓存池的脏页立刻写回磁盘,但日志必须要先被立刻写回磁盘

DBMS可以周期性地检查page table,将脏页刷回磁盘。

其他类型缓存

DBMS不仅需要缓存磁盘上的文件数据,还需要缓存其他的东西,比如说热点的SQL语句的执行结果,WAL策略中的日志,etc.

这本质上是因为磁盘I/O的开销太大,因此需要使用内存作为磁盘读/写时的缓存。

总结

The DBMS can almost always manage memory better than the OS.

作者

Desirer

发布于

2024-04-10

更新于

2026-02-21

许可协议