缓冲区管理
专栏内容:
- 手写数据库toadb
本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。
本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,方便阶段学习。
开源贡献:
- toadb开源库
个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
文章目录
- 缓冲区管理
- 前言
- 概述
- 缓冲区管理结构
- 缓冲区管理策略
- 缓冲区管理与查询执行的关系
- 总结
- 结尾
前言
随着信息技术的飞速发展,数据已经渗透到各个领域,成为现代社会最重要的资产之一。在这个大数据时代,数据库理论在数据管理、存储和处理中发挥着至关重要的作用。然而,很多读者可能对数据库理论感到困惑,不知道如何选择合适的数据库,如何设计有效的数据库结构,以及如何处理和管理大量的数据。因此,本专栏旨在为读者提供一套全面、深入的数据库理论指南,帮助他们更好地理解和应用数据库技术。
数据库理论是研究如何有效地管理、存储和检索数据的学科。在现代信息化社会中,数据量呈指数级增长,如何高效地处理和管理这些数据成为一个重要的问题。同时,随着云计算、物联网、大数据等新兴技术的不断发展,数据库理论的重要性日益凸显。
因此,本专栏的分享希望可以提高大家对数据库理论的认识和理解,对于感兴趣的朋友带来帮助。
概述
为了更快的查询,我们操作的数据都是加载到缓冲区中,为了更好的得到缓冲区,尽可能的缩小得到缓冲区的延迟,减少不可能满足要求的情况,就需要缓冲区管理器。
本文主要分享缓冲区管理的策略,以及缓冲区管理器的作用。
缓冲区管理结构
数据库的执行模块一般都直接与缓冲区交互,而当需要的数据不在缓冲区时,由缓冲区和磁盘之间交互,加载对应的数据。
一般有两种缓冲区管理结构:
- 在大多数关系型DBMS中,缓冲区管理器直接控制内存;
- 缓冲区管理器在虚拟内存中分配缓冲区,允许操作系统来决定缓冲区在何时真正在内存中,以及那些缓冲区在操作系统管理的磁盘的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)
来调用函数。
结尾
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。