Postgresql 中文操作指南

61.1. Creating Custom Scan Paths #

自定义扫描提供程序通常会通过设置以下挂钩为基础关系添加路径,该挂钩在核心代码为关系生成所有可用的访问路径后调用(除了 Gather 路径之外,这些路径是在此调用之后创建的,以便它们可以使用该挂钩添加的部分路径):

A custom scan provider will typically add paths for a base relation by setting the following hook, which is called after the core code has generated all the access paths it can for the relation (except for Gather paths, which are made after this call so that they can use partial paths added by the hook):

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 对象,该对象声明如下:

Although this hook function can be used to examine, modify, or remove paths generated by the core system, a custom scan provider will typically confine itself to generating CustomPath objects and adding them to rel using add_path. The custom scan provider is responsible for initializing the CustomPath object, which is declared like this:

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 必须指向(通常是静态分配的)实现必需的自定义路径方法的对象,我们在下面将进一步详细介绍它们。

path must be initialized as for any other path, including the row-count estimate, start and total cost, and sort ordering provided by this path. flags is a bit mask, which specifies whether the scan provider can support certain optional capabilities. flags should include CUSTOMPATH_SUPPORT_BACKWARD_SCAN if the custom path can support a backward scan, CUSTOMPATH_SUPPORT_MARK_RESTORE if it can support mark and restore, and CUSTOMPATH_SUPPORT_PROJECTION if it can perform projections. (If CUSTOMPATH_SUPPORT_PROJECTION is not set, the scan node will only be asked to produce Vars of the scanned relation; while if that flag is set, the scan node must be able to evaluate scalar expressions over these Vars.) An optional custom_paths is a list of Path nodes used by this custom-path node; these will be transformed into Plan nodes by planner. custom_private can be used to store the custom path’s private data. Private data should be stored in a form that can be handled by nodeToString, so that debugging routines that attempt to print the custom path will work as designed. methods must point to a (usually statically allocated) object implementing the required custom path methods, which are further detailed below.

自定义扫描提供程序也可以提供联接路径。对于基础关系,这样的路径必须生成常规会由它所替代的联接会生成的相同输出。为此,联接提供程序应设置以下挂钩,然后在挂钩函数中为联接关系创建 CustomPath 路径。

A custom scan provider can also provide join paths. Just as for base relations, such a path must produce the same output as would normally be produced by the join it replaces. To do this, the join provider should set the following hook, and then within the hook function, create CustomPath path(s) for the join relation.

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;

对于相同的联接关系,此挂钩将重复调用,其中内部和外部关系的组合不同;挂钩的任务是将重复工作最小化。

This hook will be invoked repeatedly for the same join relation, with different combinations of inner and outer relations; it is the responsibility of the hook to minimize duplicated work.

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

Convert a custom path to a finished plan. The return value will generally be a CustomScan object, which the callback must allocate and initialize. See Section 61.2 for more details.

List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root,
                                          List *custom_private,
                                          RelOptInfo *child_rel);

在将由给定子关系 child_rel 的最顶级父元素参数化的路径转换为由子关系参数化时,会调用此回调。此回调用于重新参数化任何路径或翻译保存在 custom_private 中的任何表达式节点_CustomPath_。回调可根据需要使用 reparameterize_path_by_childadjust_appendrel_attrsadjust_appendrel_attrs_multilevel

This callback is called while converting a path parameterized by the top-most parent of the given child relation child_rel to be parameterized by the child relation. The callback is used to reparameterize any paths or translate any expression nodes saved in the given custom_private member of a CustomPath. The callback may use reparameterize_path_by_child, adjust_appendrel_attrs or adjust_appendrel_attrs_multilevel as required.