PostgreSQL 9.3.1 文档 | ||||
---|---|---|---|---|
上一页 | 上一级 | 章 52. 写一个外部数据封装器 | 下一页 |
FDW回调函数GetForeignRelSize
,
GetForeignPaths
, GetForeignPlan
和
PlanForeignModify
必须适合PostgreSQL规划器的工作。
这有一些他们必须做的说明。
在root和baserel中的信息可以用于减少从外表中(因此降低成本)读取的信息量。 baserel->baserestrictinfo特别有趣,正如它包含应该用于过滤读取的行的限制资格测试(WHERE clauses)。 (FDW本身不需要执行这些测试,正如核心执行者反而可以检查它们。) baserel->reltargetlist可以用于决定需要抓取哪个列;但是注意它仅仅列出通过 ForeignScan规划节点发出的列,不是在质量评估中使用的列也不是查询输出列。
各种私有字段可用于FDW规划函数保持信息。一般来说,无论在FDW私有字段存储什么 应该是palloc,所以它将在规划结束后被回收。
baserel->fdw_private是空指针,可用于FDW规划函数存储与特定外表相关的
信息。当创建baserel结点时,核心规划器并不接触它除了初始化为NULL外。
从GetForeignRelSize
到GetForeignPaths
和/或者
GetForeignPaths
到GetForeignPlan
传递信息是非常有用的,
从而避免重复计算。
GetForeignPaths
可以通过在ForeignPath节点的
fdw_private字段存储私有信息标识不同访问路径的含义。
作为List指针声明fdw_private,但是实际上可以包含任何由于
核心规划器没有接触的东西。然而,最好办法是通过nodeToString
可倾式表示形式,
用于调试后端可用支持。
GetForeignPlan
可以检查所选的ForeignPath节点的
fdw_private字段,并且可以产生放在ForeignScan
规划节点中的fdw_exprs和fdw_private列表,
在执行时间他们可用。这些列表必须在copyObject
知道如何拷贝的形式中被表示。
fdw_private列表没有其他限制,并且不能通过任何方式的核心后端进行解释。
fdw_exprs列表如果不是零,那么希望包含在运行时执行的表达式树。
这些树将通过规划器使得它们完全可执行进行后处理。
在GetForeignPlan
中,往往目标列表可以拷贝到规划节点中。
已通过的scan_clauses列表包含和baserel->baserestrictinfo相同分句,
但是为了更好的执行效率可能重新排序。
在简单情况下FDW可以从scan_clauses列表(使用extract_actual_clauses
)中删除RestrictInfo节点,
并且将所有分句放入规划节点的资格列表中,这意味着在运行期间通过执行器将检查所有分句。
更多复杂的FDW可能检查一些内部分句,在这种情况下那些分句可以从规划节点的列表中删除,以便执行器
不会浪费复查它们的时间。
作为一个例子,FDW可能标识一些来自foreign_variable =
sub_expression的限制分句,它决定了在给定sub_expression的本地评估值的
远程服务器上被执行。在GetForeignPaths
期间产生了该分句的实际标识,
因为它会影响路径的成本估算。路径的fdw_private字段可能包含一个指向
已标识分句的RestrictInfo节点的指针。然后GetForeignPlan
从scan_clauses中
删除该分句,但是增加sub_expression到fdw_exprs以确保
它获得可执行形式。它也可能将控制信息放到规划节点的fdw_private
字段以告知执行函数在运行时间执行什么。传送到远程服务器的查询可能涉及到像WHERE foreign_variable =
$1的一些内容,使用从fdw_exprs表达式树评估中获得的参数值。
FDW应该总是构建至少一个仅仅依赖于表的限制分句的路径,在连接查询中,它也可能选择构建依赖于连接分句的路径,
比如 foreign_variable =
local_variable。该分句没有在baserel->baserestrictinfo中找到,
但是必须在关系的连接列表中寻找。
使用分句的路径被称为"参数化路径"。
它必须标识用于使用param_info合适值的已选择连接分句的其他关系;
使用get_baserel_parampathinfo
计算该值。在GetForeignPlan
中,
连接分句的local_variable部分将被添加到fdw_exprs中,
然后运行时该情况与普通限制分句一样运行。
当规划一个UPDATE或者DELETE的时候,
PlanForeignModify
可以查找外表的RelOptInfo结构,
并且充分使用通过扫描规划函数预先创建的baserel->fdw_private数据。
然而,在INSERT中不扫描目标表,所以没有RelOptInfo。
通过PlanForeignModify
返回的List与ForeignScan规划节点
的fdw_private列表有相同的限制,
即它必须包含copyObject
知道如何拷贝的结构。
UPDATE或者DELETE反对外部数据源支持并发更新,推荐 ForeignScan操作锁定抓取的行,也许通过SELECT FOR UPDATE的等价物。 当在SELECT FOR UPDATE/SHARE引用外表时,FDW可能也会在抓取时选择锁定行。 如果没有做,就有关外表来说, 那么FOR UPDATE或者FOR SHARE选项本质上是无操作的。 这种操作可能会产生本地表操作上轻微的语义差异,行锁定通常尽可能的延迟: 远程行可能获得锁定即使他们随后没有本地应用限制或者连接条件。 然而,匹配局部语义确实需要每行的额外远程访问,并且不可能依赖于 外部数据源提供的锁定语义内容。