摘要:
数据库的查询模型比较经典的是火山模型, 其实就是流水线操作, 例如mysql.
作为对应的便是物化模型, 例如monetdb.
列存数据库自从monetdb的开创性paper开始, 几乎都是采用了物化模型. 并且一定程度上结合了流水线操作, 例如duckdb.
本文做些简要的分析.
流水线操作/火山模型:
- 更为常见的名字是所谓的火山模型
- 比较典型的特征就是在每一个操作符或者说算子中以迭代器的方式传递数据
- 在函数实现上便是以next为操作核心, 可以参考mysql的sub_select函数的实现
- 由于操作符是逐个元组的传递并计算, 内存的使用从而可以保持在单个元组以及投影的结果集相关
- 由于并非是以磁盘块来进行读取, 而是以元组为基础, 导致更高次数的磁盘IO
- 流水线操作对cpu的cache和pipeline不友好, 每个操作符的迭代器存在分支判断和分支预测, 导致cache和pipeline分支预测失效, 这也是被montedb极为抨击的点, 并以此导致monetdb采取了全量物化模型
- 往好处看, 由于操作符的处理都被流水线化, 所以便于进行不同操作符的并行执行, 这点上可以参考duckdb
- 在经典的流水线操作中, 一些操作符的物理策略也会采取物化模型, 典型的就是mysql的hash join策略
物化模型:
- 比较经典的是monetdb的paper中的思想 https://www.cidrdb.org/cidr2005/papers/P19.pdf
- 理论基础是现代CPU的多核特性, cpu cache, cpu pipeline预处理
- 可以说现在的列存储引擎都依据此思想来做
- 典型的特点便是对每个操作符都执行全量操作, 对于列存更有意思, 生成一个全新的列, 这点上可以参考monetdb的BAT, 以及clickhouse对于列的传递
- 由于执行全量操作占用的内存与该操作符以及表的数据量相关, 所以为了减少对内存的占用, 避免磁盘IO的颠簸, 将物化与流水线操作集合, 以控制内存和磁盘的数据交换频率
- 物化这个名字容易让人误解为是将中间结果持久化到磁盘, 但是更多的是在内存中进行物化