diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-07 15:58:22 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-07 15:58:22 -0500 |
commit | 3fc6e2d7f5b652b417fa6937c34de2438d60fa9f (patch) | |
tree | 8702775168bd6a68c44c398875fa0ef70d204128 /doc/src | |
parent | b642e50aea1b966f3b78c49e806b4a2c5497a861 (diff) |
Make the upper part of the planner work by generating and comparing Paths.
I've been saying we needed to do this for more than five years, and here it
finally is. This patch removes the ever-growing tangle of spaghetti logic
that grouping_planner() used to use to try to identify the best plan for
post-scan/join query steps. Now, there is (nearly) independent
consideration of each execution step, and entirely separate construction of
Paths to represent each of the possible ways to do that step. We choose
the best Path or set of Paths using the same add_path() logic that's been
used inside query_planner() for years.
In addition, this patch removes the old restriction that subquery_planner()
could return only a single Plan. It now returns a RelOptInfo containing a
set of Paths, just as query_planner() does, and the parent query level can
use each of those Paths as the basis of a SubqueryScanPath at its level.
This allows finding some optimizations that we missed before, wherein a
subquery was capable of returning presorted data and thereby avoiding a
sort in the parent level, making the overall cost cheaper even though
delivering sorted output was not the cheapest plan for the subquery in
isolation. (A couple of regression test outputs change in consequence of
that. However, there is very little change in visible planner behavior
overall, because the point of this patch is not to get immediate planning
benefits but to create the infrastructure for future improvements.)
There is a great deal left to do here. This patch unblocks a lot of
planner work that was basically impractical in the old code structure,
such as allowing FDWs to implement remote aggregation, or rewriting
plan_set_operations() to allow consideration of multiple implementation
orders for set operations. (The latter will likely require a full
rewrite of plan_set_operations(); what I've done here is only to fix it
to return Paths not Plans.) I have also left unfinished some localized
refactoring in createplan.c and planner.c, because it was not necessary
to get this patch to a working state.
Thanks to Robert Haas, David Rowley, and Amit Kapila for review.
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/fdwhandler.sgml | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml index 9ad4e1c9601..279daef2d16 100644 --- a/doc/src/sgml/fdwhandler.sgml +++ b/doc/src/sgml/fdwhandler.sgml @@ -1317,6 +1317,40 @@ GetForeignServerByName(const char *name, bool missing_ok); </para> <para> + An FDW might additionally support direct execution of some plan actions + that are above the level of scans and joins, such as grouping or + aggregation. To offer such options, the FDW should generate paths + (probably ForeignPaths or CustomPaths) and insert them into the + appropriate <firstterm>upper relation</>. For example, a path + representing remote aggregation should be inserted into the relation + obtained from <literal>fetch_upper_rel(root, UPPERREL_GROUP_AGG, + NULL)</>, using <function>add_path</>. This path will be compared on a + cost basis with local aggregation performed by reading a simple scan path + for the foreign relation (note that such a path must also be supplied, + else there will be an error at plan time). If the remote-aggregation + path wins, which it usually would, it will be converted into a plan in + the usual way, by calling <function>GetForeignPlan</>. + </para> + + <para> + <function>PlanForeignModify</> and the other callbacks described in + <xref linkend="fdw-callbacks-update"> are designed around the assumption + that the foreign relation will be scanned in the usual way and then + individual row updates will be driven by a local <literal>ModifyTable</> + plan node. This approach is necessary for the general case where an + update requires reading local tables as well as foreign tables. + However, if the operation could be executed entirely by the foreign + server, the FDW could generate a path representing that and insert it + into the <literal>UPPERREL_FINAL</> upper relation, where it would + compete against the <literal>ModifyTable</> approach. This approach + could also be used to implement remote <literal>SELECT FOR UPDATE</>, + rather than using the row locking callbacks described in + <xref linkend="fdw-callbacks-row-locking">. Keep in mind that a path + inserted into <literal>UPPERREL_FINAL</> is responsible for + implementing <emphasis>all</> behavior of the query. + </para> + + <para> When planning an <command>UPDATE</> or <command>DELETE</>, <function>PlanForeignModify</> can look up the <structname>RelOptInfo</> struct for the foreign table and make use of the |