选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

Chapter 58. 编写自定义扫描提供者

PostgreSQL 支持一组实验性功能,旨在允许扩展模块向系统中添加新的扫描类型。与外部数据包装器不同,后者只负责了解如何扫描其自身的外部表,而自定义扫描提供者则可以为系统中的任何关系提供一种替代扫描方法。通常,编写自定义扫描提供者的动机,是为了能够使用某些核心系统尚不支持的优化,例如缓存或某种形式的硬件加速。本章概述如何编写新的自定义扫描提供者。

实现一种新的自定义扫描类型分为三个步骤。首先,在规划期间,需要生成表示使用所提策略进行扫描的访问路径。其次,如果规划器从这些访问路径中选出一条,作为扫描某个特定关系的最优策略,就必须将该访问路径转换为计划。最后,还必须能够执行该计划,并生成与针对同一关系的其他访问路径原本会生成的结果相同的结果。

58.1. 创建自定义扫描路径 #

自定义扫描提供者通常通过设置下面的钩子,为基表添加路径。核心代码为该关系生成所有可生成的访问路径之后,会调用此钩子(Gather 路径除外,它们会在本次调用之后生成,以便使用钩子添加的部分路径):

typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
                                            RelOptInfo *rel,
                                            Index rti,
                                            RangeTblEntry *rte);
extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;

虽然此钩子函数可用于检查、修改或删除核心系统生成的路径,但自定义扫描提供者通常只生成CustomPath对象,并将它们添加到rel,所用函数是add_path。自定义扫描提供者负责初始化CustomPath对象,其声明如下:

typedef struct CustomPath
{
    Path      path;
    uint32    flags;
    List     *custom_paths;
    List     *custom_private;
    const CustomPathMethods *methods;
} CustomPath;

path 必须像其他任何路径一样完成初始化,包括行数估计、启动代价和总代价,以及该路径提供的排序顺序。flags 是一个位掩码,如果自定义路径支持反向扫描,就应包含 CUSTOMPATH_SUPPORT_BACKWARD_SCAN;如果支持标记和恢复,就应包含 CUSTOMPATH_SUPPORT_MARK_RESTORE。这两种能力都是可选的。可选字段 custom_paths 是该自定义路径节点所使用的 Path 节点列表;规划器会把它们转换成 Plan 节点。custom_private 可用于存储自定义路径的私有数据。私有数据应以 nodeToString 能够处理的形式存储,这样尝试打印该自定义路径的调试例程才能按预期工作。methods 必须指向一个实现了所需自定义路径方法的对象(通常是静态分配的),目前只有一种此类方法。

自定义扫描提供者也可以提供连接路径。与基本关系一样,这种路径也必须产生与它所替代连接通常会产生的相同输出。为此,连接提供者应设置下列钩子,并在该钩子函数内部为连接关系创建 CustomPath 路径。

typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
                                             RelOptInfo *joinrel,
                                             RelOptInfo *outerrel,
                                             RelOptInfo *innerrel,
                                             JoinType jointype,
                                             JoinPathExtraData *extra);
extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;

对于同一个连接关系,这个钩子会针对不同的内外关系组合重复调用;如何尽量减少重复工作,是该钩子的职责。

58.1.1. 自定义扫描路径回调 #

Plan *(*PlanCustomPath) (PlannerInfo *root,
                         RelOptInfo *rel,
                         CustomPath *best_path,
                         List *tlist,
                         List *clauses,
                         List *custom_plans);

将自定义路径转换为完成的计划。返回值通常是一个 CustomScan 对象,回调函数必须负责分配并初始化该对象。详见 Section 58.2