RDBMS关键技术
在前文中,我们简要介绍了SQL引擎中的解析器Parser和优化器Optimizer,这里将继续介绍SQL引擎中的执行器Executor。执行器Executor
在Optimizer输出最优的执行计划Plan后,Executor负责执行计划并得到结果。在第一次接触到Executor时,我只是单纯的把它当做一个执行工具,只需要机械地执行得到的Plan就可以了,就像写好的程序被按部就班地逐行执行。但在深入了解后发现并不是如此,Executor同样有很多探讨和优化的空间。
这里先介绍一下最常见的火山模型。 执行计划Plan仍然保持着查询树AST的结构,树的每个节点是代数运算符(Operator)。火山模型把会Operator看成是一个个迭代器,每个迭代器都会提供一个next()接口。所以在执行过程中,会自顶向下地调用每个Operator的next()接口,并逐级向上返回tuple数据。当前Operator得到子节点返回的tuple数据后会执行其定义的处理并向上返回。火山模型的这种处理方式也称为拉取执行模型(Pull Based)。针对以上的处理过程,可见火山模型的耦合性很低,每一个Operator只需要关心自己需要处理的内容即可,逻辑清晰。
在传统的数据库查询执行模式(如上述火山模型的执行过程)中,执行器一次只处理一个元组(一行数据),这被称为"一次一tuple"的执行模式。很显然,"一次一tuple" 的执行模式存在一些性能瓶颈。因为在这种模式下,执行器需要逐行遍历查询操作树,并逐个处理每个元组的数据,导致CPU大部分时间花在遍历操作树上,而不是实际的数据处理。这可能导致CPU的有效利用率较低,并且会产生指令缓存性能下降和频繁的跳转操作,影响性能。
为了充分利用现代硬件的能力并加速查询的执行,提出了一种新的执行模式,即"一次一列"的模式,也被称为向量化执行引擎。在这种模式下,执行器一次会处理一列数据,而不是一行数据。这意味着执行器会对整列数据进行操作,从而充分利用了现代硬件的向量化指令集和内存访问模式,提高了执行效率。向量化执行引擎的核心思想是将操作应用于整个列,从而减少循环迭代和跳转,提高了CPU的利用率和指令缓存性能。SQL查询在数据库中经过解析,会生成一棵查询树,查询数的每个节点为代数运算符(Operator)。向量化执行仍然可以采取火山模型的拉取模式,但是每次拉取的数据就可以是多个元组,实现多行并发处理。
当然了,以上都是个人仅根据阅读过的各种资料后得到的很浅显的理解,并没有系统地了解过实现原理,仅供参考。