定义
PG虽然是C语言,但是其代码实现包含很多面向对象的思想,主要包含:
- 继承:通过将一个结构体(作为基类)放到另一个结构体(作为子类)的第一个字段,从而实现继承。
- 方法:通过在结构体中定义函数指针类型的字段,从而实现属性和方法的绑定
- 接口类:将一系列函数指针封装为一个结构体,该结构体只有方法没有属性,就是接口类(类似C++纯虚类)
方案分析
经过前期分析,我们基于社区PG14版本,整理出社区关于TableAM的特性修改集中在26个提交,涉及文件修改286处,新增代码10012行,删除代码5939行。主要涉及的改动如下:
- 对一些核心的数据结构进行了抽象和优化:将其调整为与具体存储引擎无关的基类,并将原有关于
Heap
表的对应结构修改为这些基类的子类,主要包括:- TupleTableSlot:在内存中存放tuple的容器类。该结构体在TeleDBX中已经存在,TableAM对其进行重新定义,包括:
- 将一些通用的字段保留在结构体中,将TupleTableSlot变成1个基类
- 在TupleTableSlot上派生出BufferHeapTupleTableSlot、HeapTupleTableSlot、MinimalTupleTableSlot和VirtualTupleTableSlot四种子类,分别对应4种tuple的管理方式
- 对TupleTableSlot相关的一系列函数抽象为TupleTableSlotOps接口类,作为属性绑定到TupleTableSlot类
- 对heap表的一系列slot相关操作进行二次封装,将其定义为4个全局的接口对象,对应4种TupleTableSlot子类
- TableScanDesc:描述顺序扫描的类。该结构体是新增的,改动包括:
- 抽象了
TableScanDesc
类型用于描述顺序扫描 - 将
HeapScanDesc
中一些字段放入TableScanDesc
,然后将HeapScanDesc
实现为其子类
- 抽象了
- ParallelTableScanDesc & ParallelBlockTableScanWorker:描述并行扫描的类,该结构体为新增,改动包括:
- 将
ParallelHeapScanDesc
拆分抽象为ParallelTableScanDesc
和ParallelBlockTableScanWorker
- 将
- IndexFetchTableData:描述索引扫描的类,该结构体是新增的,改动包括:
- 在
IndexScanDescData
对象中增加了IndexFetchTableData
类型的属性xs_heapfetch
- 基于
IndexFetchTableData
对象在TableAmRoutine
中封装了一系列索引扫描的方法
- 在
- TupleTableSlot:在内存中存放tuple的容器类。该结构体在TeleDBX中已经存在,TableAM对其进行重新定义,包括:
- 引入了TableAmRoutine这个接口类作为自定义存储引擎的接口,其包含了一系列接口,主要包括:
- 对应TupleTableSlot对象的TupleTableSlotOps接口类
- 顺序扫描方法
- 并行扫描方法
- 索引扫描方法
- 元组读相关方法
- 元组写相关方法
- DDL相关方法
- Planner相关方法
- Executor相关方法
- 其它方法
- 将现有heap表作为一种存储引擎,适配到TableAM
- 将一些核心的类封装为TableAM类的子类
- 将一些核心的方法封装为TableAM类的方法
- 将执行器中与存储引擎的对接代码从heap接口转换为TableAM虚函数
- 元数据修改
- pg_type新增类型:table_am_handler
- pg_proc新增函数:heap_tableam_handler、table_am_handler_in、table_am_handler_out
- pg_class一些系统表的relam字段值变更为PGHEAPAM
- 语法及功能
- 扩展
CREATE ACCESS METHOD
语法,在IndexAM基础上支持TableAM CREATE TABLE
增加table_access_method_clause
,指定TableAM
- 扩展
- 其它修改
- 要通过ObjectAddress建立Reletion和其AccessMethod对象的依赖关系
- 新增了
default_table_access_method
参数指定默认的TableAccessMethod
- 修改
\d
表结构的描述信息,增加TableAccessMethod
相关描述信息(可选)
除了上诉修改,在合入过程中还有几个需要考虑的点:
- PG14相对TeleDB for Xscale的基线版本PG10有很多新增特性
- TeleDB for Xscale作为分布式数据库,和PG也会有大量不同的地方
而TableAM作为从代码层面进行的优化,涉及大量接口的新增、删除和调整,必然会存在不兼容的地方,导致无法直接合入社区patch,只能在理解patch的基础上将其适配到TeleDB for Xscale内核,过程中要基于如下原则:
- 结构体要保持完全兼容,必要情况下可以增加字段
- 方法的参数保持完全兼容,必要情况下可以增加参数
具体到执行阶段,有两种策略:
- 基于社区commit,逐个合入并进行测试验证
- 直接基于社区最新代码,通过对比进行整体合入,最后整体测试验证
最后综合考虑工作量和可执行路径,我们选择了后者,理由如下:
- 社区很多commit也处于中间状态,会有方案来回调整的情况,挨个commit合入等于重复这些方案调整的过程,工作量巨大
- 由于TeleDB for Xscale相对于社区PG,在内核层面已经进行了大量修改,很多commit都需要进行人工修改适配,而带个commit进行这种适配无疑会进一步增加工作量
总结
目前TeleDB for Xscale已经完成了TableAM框架的引入工作,并在此基础上引入了原地更新引擎和列存引擎等多个存储引擎。