【数据库】缓冲区管理器结构,几种常用替换策略分析,pin钉住缓冲区块防止错误的替换,以及缓冲区管理带来的代价优化

缓冲区管理

专栏内容

  • 手写数据库toadb
    本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。
    本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,方便阶段学习。

开源贡献

个人主页我的主页
管理社区开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.


在这里插入图片描述

前言

随着信息技术的飞速发展,数据已经渗透到各个领域,成为现代社会最重要的资产之一。在这个大数据时代,数据库理论在数据管理、存储和处理中发挥着至关重要的作用。然而,很多读者可能对数据库理论感到困惑,不知道如何选择合适的数据库,如何设计有效的数据库结构,以及如何处理和管理大量的数据。因此,本专栏旨在为读者提供一套全面、深入的数据库理论指南,帮助他们更好地理解和应用数据库技术。

数据库理论是研究如何有效地管理、存储和检索数据的学科。在现代信息化社会中,数据量呈指数级增长,如何高效地处理和管理这些数据成为一个重要的问题。同时,随着云计算、物联网、大数据等新兴技术的不断发展,数据库理论的重要性日益凸显。

因此,本专栏的分享希望可以提高大家对数据库理论的认识和理解,对于感兴趣的朋友带来帮助。

概述

为了更快的查询,我们操作的数据都是加载到缓冲区中,为了更好的得到缓冲区,尽可能的缩小得到缓冲区的延迟,减少不可能满足要求的情况,就需要缓冲区管理器。

本文主要分享缓冲区管理的策略,以及缓冲区管理器的作用。

缓冲区管理结构

数据库的执行模块一般都直接与缓冲区交互,而当需要的数据不在缓冲区时,由缓冲区和磁盘之间交互,加载对应的数据。

一般有两种缓冲区管理结构:

  1. 在大多数关系型DBMS中,缓冲区管理器直接控制内存;
  2. 缓冲区管理器在虚拟内存中分配缓冲区,允许操作系统来决定缓冲区在何时真正在内存中,以及那些缓冲区在操作系统管理的磁盘的swap空间中。许多内存型数据库和面向对象的数据库会按这种方式操作。

不管使用那种结构,都会引起同样的问题 :缓冲区管理器应当限制使用缓冲区的数量,使得它们能够适合内存的容量。

当采用缓冲区管理器直接管理内存的结构时,请求的缓冲区数量,超过了可得到的空间时,就不得不通过将缓冲区的内容刷到磁盘上,来清理一部分缓冲区。

而当使用虚拟内存方式时,可得到的空间会超过真正的内存容量,如果缓冲区超过物理内存容量时,操作系统就会将多块内存在磁盘swap区移进移出,使性能出现波动,系统也会花费大量时间来作交换。

缓冲区管理策略

为了避免缓冲区超过可用上限,带来严重的波动,缓冲区管理器必须给出缓冲区的一个合理使用上限,而到达这一上限之后,需要采用一定策略来保证我们可用的缓冲区请求不被延迟。

这正如大家所熟悉的操作系统的内存调度替换策略,一般有以下几种:

  • 最近最少使用 LRU

LRU策略是替换出最长时间没有读或写过的块;这种方法要求缓冲区管理器维护一张表,来记记录每个缓冲区被最后访问的时间,每次访问都需要生成或更新这个表项,有一定的维护工作量。但是LRU是一个有效的策略。

  • 先进先出 FIFO

在FIFO策略中,当需要一个缓冲区时,需要清空占用时间最长的那个缓冲区,并用来装入请求的数据块。在这种方法中,缓冲区管理器同样也要记录一张表,来记录每个缓冲区的访问时间,当新缓冲区时才会生成表项,再次访问并不会更新表项。

相比LRU,FIFO更少的维护成本,但是它会造成更多的错误,使用最频繁的块反而会被替换出去,又很快又被加载。

  • “时钟”算法

这个算法,可以看成是LRU算法的一种实现,它更有效。将缓冲区看作一个环,一个遍历指示器指向缓冲区中的一个,如果想找到一个可用缓冲区,指示器就按顺时针旋转查找。

每个缓冲区有一个标记,它可以是0或1,当标志为0时,就可以被选中,替换当前缓冲区的内容到磁盘上,同时加载新请求的数据块到缓冲区中,并置为1;如果指示器遇到的缓冲区标记为1,就将它减为0,这样在下一次循环到时,就可以选择;

同样的,当缓冲区被访问时,也会将标记设置为1,这样说明最近被使用过,减少替换的概率。

指示器查找时,直到找到缓冲区标记为0的缓冲区为直,最多会查找第二遍就可以找到。

当然这个标志的取值,可以用更大的数字,意味着指示器在缓冲区上限较小时,需要循环更多遍。

  • 系统控制

查询执行器或者其它数据库模块,可以给缓冲区管理器一些建议,避免像LRU,FIFO,时钟”算法等这些严格的策略引起错误。

比如“钉住”某一缓冲区块,暂时绕过策略控制,比如之前博客提到的一趟算法中,正在一条接一条元组扫描时,这个数据块就不能被替换出去。还有对于正在用到的B树索引的根数据块,它是非常频繁被访问的。

这样可以保持该缓冲区一直在内存中,等到使用完成时,解除就可以使用策略进行替换。

缓冲区管理与查询执行的关系

当执行时,需要得到M个缓冲区时,缓冲区管理器能够保证它得到足够的缓冲区吗?

在缓冲区管理器设计时需要考虑两个问题 :

  • 替换算法能够适应得到的缓冲区数目M的变化;
  • 缓冲区替换给执行带来的额外磁盘I/O数量;

这就需要缓中区管理和执行算法都有一定的适应性;对于第二个问题,需要缓冲区管理器,在占用一定缓冲区后,就要进行提前清理缓冲区,减少需求时的等待代价。

总结

通过对于缓中区管理器的了解,可以看到它的实现策略也是我们熟悉的几种算法,当然会存在一些在实践中的问题,需要在使用时注意。

最后分享一段helloworld的代码

#include <stdio.h>

void hello(void) {
    
    
    printf("Hello, World!\n");
}

int main(void) {
    
    
    void (*func_ptr)(void) = hello;
    (*func_ptr)();
    return 0;
}

在这个例子中,我们定义了一个名为 hello 的函数,它输出 “Hello, World!”。然后,在 main 函数中,我们定义了一个名为 func_ptr 的函数指针,并将其指向 hello 函数。最后,我们通过 (*func_ptr)() 来调用 hello 函数。注意,在使用函数指针时,我们需要使用 (*func_ptr) 来调用函数。

结尾

非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:[email protected]
如有错误或者疏漏欢迎指出,互相学习。

猜你喜欢

转载自blog.csdn.net/senllang/article/details/134632685
今日推荐