执行器作为连接查询计划和存储引擎的桥梁,负责从存储引擎读取数据,并基于查询计划树执行对应的算子,并得到最终的查询结果。
执行器的处理模型主要分为两大类:基于拉操作的模型和基于推操作的模型。
也被称为火山模型,是指从最顶层的输出节点开始,不断从下层节点拉取数据,因此是一种自顶向下的执行方式。
优点
不足
Push模型:从最底层的节点开始,不断生成数据,并向上层节点进行数据推送,因此是一种自底向上的执行方式。推模型本质是一种基于物化的操作,每一个节点处理所有的输入数据,并将处理后的数据进行物化,并传递给上层节点。
优点
不足
除了拉模型和推模型两大基础模型之外,还引入向量化执行引擎。
1.执行器与算子如何关联?
通过三部曲:ExecutorStart、ExecutorRun、ExecutorEnd。
2.查询计划与执行器如何关联?
通过Portal。
Portal记录了与执行相关的所有信息,例如查询树、计划树和执行状态。对于用户提交的普通查询语句,执行器会创建一个匿名的Portal对象。游标语句,执行器会创建一个对应的命名Portal对象。
3.执行器与存储层如何关联?
通过table am与scan/modifyTable算子进行关联。
SQL语句中除了SELECT、FROM、WHERE、GROUP BY等关键字之外的部分,都可以被认为是某种表达式。
例如:a列,a + 1,a * b等等。
表达式名 | 示例 |
---|---|
常量表达式 | 10 |
列引用 | i, j |
位置参数引用 | $1 |
下标 | arr[i] |
域选择表达式 | table.column |
运算符表达式 | a > b, x and y, x or y |
函数表达式 | upper(name), now() |
聚集表达式 | coumt(*), avg(salary) |
窗口函数 | sum(salary) over (partition by department) |
标量子查询 | select (select max(age) from students) from student; |
数组表达式 | select array[1, 2, 3] |
Row表达式 | select row(1, 'John Doe') |
记录下每次表达式评估所需要的tuple,可能来自scan、outer、inner。
TupleTableSlot *ecxt_scantuple;
TupleTableSlot *ecxt_innertuple;
TupleTableSlot *ecxt_outertuple;
ExprState 是表达式求值的顶级节点,它包含:
对于一个表达式树,每个node初始化为ExprEvalOp,ExprEvalStep 存储每一步表达式评估的结果。
假设有一个数据库需求,需要添加一个数据检查的功能,会检查其输入的数据,并对数据进行验证,如果发现数据不符合条件,则会抛出错误或者警告。
例如:plan如下
-> Assert
Assert Cond: (i = 1)
-> Seq Scan
我们如何为数据库新增一个AssertOp算子呢?(不考虑优化器,只考虑执行器)
以上就是本次的分享,欢迎转发与收藏。