Processing Models
DBMS的处理模型定义了系统是如何执行查询计划的。主要有以下三种模型:
- 迭代器模型
- 物化模型
- 矢量化模型
迭代器模型
迭代器模型中每个算子都实现了next()函数。
这些算子通过调用next函数来向child算子来获取单个tuple或者结束信号并处理他们,从而实现了循环。
每个算子都还有一个open函数和close函数,类似于类中的构造函数和析构函数。
迭代器模型也被称为火山模型或者管道模型。现如今大多数DBMS都使用的这种模型。
物化模型
物化模型中每个算子都是一次性处理全部的输入并且一次性全部发送出去,因此算子中也没有next函数。 DBMS还会把Limit这样的信息下推下去以避免读取太多的数据。算子的输出结果可以是物化的一整行数据或者单个列的数据。
物化模型更适用于OLTP场景,因为OLTP场景更多的是查询小数据量的Query, 而对于中间结果数据量较大的OLAP场景不太适用。
矢量化模型
矢量化模型类似于迭代器模型,每个算子都实现了next函数,区别在于矢量化模型每次传输批量的数据。因此算子们内部的一次循环就可以处理大量数据。具体每次批处理多少数据,需要取决于硬件和查询参数。
矢量化模型非常适合于OLAP场景,因为他可以大大减少每个算子调用的次数,并且能够让使用者更容易地利用SIMD指令来处理批量数据。
Access Methods
Access Methods是指DBMS访问表中数据的方式,主要有以下三种:
- Sequential Scan
- Index Scan
- Multi-Index Scan
Sequential Scan
Sequential Scan指的是对于表中的每个Page,DBMS会从缓冲池中去获取,然后遍历每一个tuple去判断是否包含。 对于Sequential Scan有以下的一些优化方法,我们这次主要讲Data Skipping.
Data Skipping主要有两种方法:
- Approximate Queries(有损): 对整个表的采样子集执行查询以生成近似结果
- Zone Maps(无损): 预先计算每个Page的聚合统计,包括min,max,sum,avg等值,然后DBMS通过这些预计算的值来判断是否需要读取这个Page
Index Scan
DBMS选择一个索引来寻找Query需要的数据
Multi-Index Scan
对于一个Query, 如果有多个可以利用的index时,会进一步提高查询效率。
比如下面的例子,可以使用age和dept的索引分别进行过滤,然后取他们两个过滤后的交集,再判断country是否为US。
Expression Evaluation
DBMS将一个where语句表示为一个expression tree。
用这种方式来判断谓词会很慢,更好的选择是使用JIT,它将表达式的计算逻辑转换为机器代码,并进行即时编译。这样,在表达式被多次执行时,可以避免每次都进行解析和解释的开销,而是直接执行编译后的机器代码,从而提高计算的速度。