Consider cheap startup paths in add_paths_to_append_rel
authorDavid Rowley <drowley@postgresql.org>
Thu, 5 Oct 2023 08:03:10 +0000 (21:03 +1300)
committerDavid Rowley <drowley@postgresql.org>
Thu, 5 Oct 2023 08:03:10 +0000 (21:03 +1300)
6b94e7a6d did this for ordered append paths to allow fast startup
MergeAppends, however, nothing was done for the Append case.

Here we adjust add_paths_to_append_rel() to have it build an AppendPath
containing the cheapest startup paths from each of the child relations
when the append rel has "consider_startup" set.

Author: Andy Fan, David Rowley
Discussion: https://www.postgresql.org/message-id/CAKU4AWrXSkUV=Pt-gRxQT7EbfUeNssprGyNsB=5mJibFZ6S3ww@mail.gmail.com

src/backend/optimizer/path/allpaths.c
src/test/regress/expected/union.out
src/test/regress/sql/union.sql

index b11b9399891098f0fd82486d85f90347da2a9afd..401290162600a174cfd7bdb7151ff3b2dedbe574 100644 (file)
@@ -1307,6 +1307,8 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
 {
    List       *subpaths = NIL;
    bool        subpaths_valid = true;
+   List       *startup_subpaths = NIL;
+   bool        startup_subpaths_valid = true;
    List       *partial_subpaths = NIL;
    List       *pa_partial_subpaths = NIL;
    List       *pa_nonpartial_subpaths = NIL;
@@ -1346,6 +1348,20 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
        else
            subpaths_valid = false;
 
+       /*
+        * When the planner is considering cheap startup plans, we'll also
+        * collect all the cheapest_startup_paths and build an AppendPath
+        * containing those as subpaths.
+        */
+       if (rel->consider_startup && childrel->pathlist != NIL &&
+           childrel->cheapest_startup_path->param_info == NULL)
+           accumulate_append_subpath(childrel->cheapest_startup_path,
+                                     &startup_subpaths,
+                                     NULL);
+       else
+           startup_subpaths_valid = false;
+
+
        /* Same idea, but for a partial plan. */
        if (childrel->partial_pathlist != NIL)
        {
@@ -1478,6 +1494,11 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
                                                  NIL, NULL, 0, false,
                                                  -1));
 
+   /* build an AppendPath for the cheap startup paths, if valid */
+   if (startup_subpaths_valid)
+       add_path(rel, (Path *) create_append_path(root, rel, startup_subpaths,
+                                                 NIL, NIL, NULL, 0, false, -1));
+
    /*
     * Consider an append of unordered, unparameterized partial paths.  Make
     * it parallel-aware if possible.
index e2613d6777e38f37a302ecc17e59df3a4cd3659c..f046e522dea5c8026dd0539b49a0d3e66b59828e 100644 (file)
@@ -1432,3 +1432,24 @@ where (x = 0) or (q1 >= q2 and q1 <= q2);
  4567890123456789 |  4567890123456789 | 1
 (6 rows)
 
+--
+-- Test the planner's ability to produce cheap startup plans with Append nodes
+--
+-- Ensure we get a Nested Loop join between tenk1 and tenk2
+explain (costs off)
+select t1.unique1 from tenk1 t1
+inner join tenk2 t2 on t1.tenthous = t2.tenthous
+   union all
+(values(1)) limit 1;
+                       QUERY PLAN                       
+--------------------------------------------------------
+ Limit
+   ->  Append
+         ->  Nested Loop
+               Join Filter: (t1.tenthous = t2.tenthous)
+               ->  Seq Scan on tenk1 t1
+               ->  Materialize
+                     ->  Seq Scan on tenk2 t2
+         ->  Result
+(8 rows)
+
index ca8c9b4d1288e1693541c044edcbb7c0307ca463..d65ca9f86debff8d3899e37dd3e6dc0733b27ed4 100644 (file)
@@ -540,3 +540,14 @@ select * from
    union all
    select *, 1 as x from int8_tbl b) ss
 where (x = 0) or (q1 >= q2 and q1 <= q2);
+
+--
+-- Test the planner's ability to produce cheap startup plans with Append nodes
+--
+
+-- Ensure we get a Nested Loop join between tenk1 and tenk2
+explain (costs off)
+select t1.unique1 from tenk1 t1
+inner join tenk2 t2 on t1.tenthous = t2.tenthous
+   union all
+(values(1)) limit 1;
\ No newline at end of file