Postgresql 中文操作指南
61.1. Creating Custom Scan Paths #
自定义扫描提供程序通常会通过设置以下挂钩为基础关系添加路径,该挂钩在核心代码为关系生成所有可用的访问路径后调用(除了 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 对象并将它们使用 add_path 添加到 rel。自定义扫描提供程序负责初始化 CustomPath 对象,该对象声明如下:
typedef struct CustomPath
{
Path path;
uint32 flags;
List *custom_paths;
List *custom_private;
const CustomPathMethods *methods;
} CustomPath;
必须像初始化任何其他路径那样初始化 path,包括此路径提供的大概行数、开始和结束代价以及排序顺序。flags 是一个位掩码,它指定扫描提供程序是否支持某些可选功能。如果自定义路径支持反向扫描,则 flags 应包括 CUSTOMPATH_SUPPORT_BACKWARD_SCAN,如果它支持标记和还原,则应包括 CUSTOMPATH_SUPPORT_MARK_RESTORE,如果它能执行投影,则应包括 CUSTOMPATH_SUPPORT_PROJECTION。(如果没有设置 CUSTOMPATH_SUPPORT_PROJECTION,则只会要求扫描节点生成所扫描关系的 Vars;而在设置该标志时,扫描节点必须能够对此类 Vars 求值标量表达式。)可选的 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;
对于相同的联接关系,此挂钩将重复调用,其中内部和外部关系的组合不同;挂钩的任务是将重复工作最小化。
61.1.1. Custom Scan Path Callbacks #
Plan *(*PlanCustomPath) (PlannerInfo *root,
RelOptInfo *rel,
CustomPath *best_path,
List *tlist,
List *clauses,
List *custom_plans);
将自定义路径转换为已完成的计划。返回值通常是 _CustomScan_对象,回调必须分配并初始化该对象。有关更多详细信息,请参阅 Section 61.2。
List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root,
List *custom_private,
RelOptInfo *child_rel);
在将由给定子关系 child_rel 的最顶级父元素参数化的路径转换为由子关系参数化时,会调用此回调。此回调用于重新参数化任何路径或翻译保存在 custom_private 中的任何表达式节点_CustomPath_。回调可根据需要使用 reparameterize_path_by_child,adjust_appendrel_attrs 或 adjust_appendrel_attrs_multilevel。