From f4e8b55ceae0f0d3b33f1822cffc9d7ed701ea30 Mon Sep 17 00:00:00 2001 From: Kyotaro Horiguchi Date: Tue, 6 Jun 2017 19:56:41 +0900 Subject: [PATCH] Support PostgreSQL 10 beta 1 step 2/2 Changed the logic to tweak parallel execution paths so that it handles more wider (parallel index scans or gather merge, specifically) range of parallel paths. --- expected/ut-W.out | 56 ++++++++++++++++++++++++++++--------------------------- pg_hint_plan.c | 51 ++++++++------------------------------------------ sql/ut-W.sql | 4 ++-- 3 files changed, 39 insertions(+), 72 deletions(-) diff --git a/expected/ut-W.out b/expected/ut-W.out index c7b9402..bb74d27 100644 --- a/expected/ut-W.out +++ b/expected/ut-W.out @@ -494,7 +494,7 @@ error hint: -> Parallel Seq Scan on p1_c3_c2 (25 rows) --- seqscan doesn't harm parallelism +-- Parallel sequential scan /*+Parallel(p1 8 hard) SeqScan(p1) */ EXPLAIN (COSTS false) SELECT * FROM p1 join p2 on p1.id = p2.id; LOG: pg_hint_plan: @@ -534,7 +534,7 @@ error hint: -> Seq Scan on p2_c3_c2 (25 rows) --- Index partial scan is not handled yet. +-- Parallel index scan /*+Parallel(p1 8 hard) IndexScan(p1) */ EXPLAIN (COSTS false) SELECT * FROM p1 join p2 on p1.id = p2.id; LOG: pg_hint_plan: @@ -545,32 +545,34 @@ not used hint: duplication hint: error hint: - QUERY PLAN --------------------------------------------------------- - Hash Join - Hash Cond: (p1.id = p2.id) - -> Append - -> Index Scan using p1_pkey on p1 - -> Index Scan using p1_c1_pkey on p1_c1 - -> Index Scan using p1_c2_pkey on p1_c2 - -> Index Scan using p1_c3_pkey on p1_c3 - -> Index Scan using p1_c4_pkey on p1_c4 - -> Index Scan using p1_c1_c1_pkey on p1_c1_c1 - -> Index Scan using p1_c1_c2_pkey on p1_c1_c2 - -> Index Scan using p1_c3_c1_pkey on p1_c3_c1 - -> Index Scan using p1_c3_c2_pkey on p1_c3_c2 - -> Hash + QUERY PLAN +----------------------------------------------------------------------- + Gather + Workers Planned: 8 + -> Hash Join + Hash Cond: (p1.id = p2.id) -> Append - -> Seq Scan on p2 - -> Seq Scan on p2_c1 - -> Seq Scan on p2_c2 - -> Seq Scan on p2_c3 - -> Seq Scan on p2_c4 - -> Seq Scan on p2_c1_c1 - -> Seq Scan on p2_c1_c2 - -> Seq Scan on p2_c3_c1 - -> Seq Scan on p2_c3_c2 -(23 rows) + -> Parallel Index Scan using p1_pkey on p1 + -> Parallel Index Scan using p1_c1_pkey on p1_c1 + -> Parallel Index Scan using p1_c2_pkey on p1_c2 + -> Parallel Index Scan using p1_c3_pkey on p1_c3 + -> Parallel Index Scan using p1_c4_pkey on p1_c4 + -> Parallel Index Scan using p1_c1_c1_pkey on p1_c1_c1 + -> Parallel Index Scan using p1_c1_c2_pkey on p1_c1_c2 + -> Parallel Index Scan using p1_c3_c1_pkey on p1_c3_c1 + -> Parallel Index Scan using p1_c3_c2_pkey on p1_c3_c2 + -> Hash + -> Append + -> Seq Scan on p2 + -> Seq Scan on p2_c1 + -> Seq Scan on p2_c2 + -> Seq Scan on p2_c3 + -> Seq Scan on p2_c4 + -> Seq Scan on p2_c1_c1 + -> Seq Scan on p2_c1_c2 + -> Seq Scan on p2_c3_c1 + -> Seq Scan on p2_c3_c2 +(25 rows) -- This hint doesn't turn on parallel, so the Parallel hint is ignored set max_parallel_workers_per_gather TO 0; diff --git a/pg_hint_plan.c b/pg_hint_plan.c index 26db50d..505ffdf 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -4433,50 +4433,24 @@ pg_hint_plan_set_rel_pathlist(PlannerInfo * root, RelOptInfo *rel, return; /* Here, we regenerate paths with the current hint restriction */ - - if (found_hints & HINT_BM_SCAN_METHOD) + if (found_hints & HINT_BM_SCAN_METHOD || found_hints & HINT_BM_PARALLEL) { - /* - * With scan hints, we regenerate paths for this relation from the - * first under the restricion. - */ + /* Just discard all the paths considered so far */ list_free_deep(rel->pathlist); rel->pathlist = NIL; - set_plain_rel_pathlist(root, rel, rte); - } - - if (found_hints & HINT_BM_PARALLEL) - { - Assert (phint); - - /* the partial_pathlist may be for different parameters, discard it */ - if (rel->partial_pathlist) + /* Remove all the partial paths if Parallel hint is specfied */ + if ((found_hints & HINT_BM_PARALLEL) && rel->partial_pathlist) { list_free_deep(rel->partial_pathlist); rel->partial_pathlist = NIL; } - /* also remove gather path */ - if (rel->pathlist) - { - ListCell *cell, *prev = NULL, *next; - - for (cell = list_head(rel->pathlist) ; cell; cell = next) - { - Path *path = (Path *) lfirst(cell); - - next = lnext(cell); - if (IsA(path, GatherPath)) - rel->pathlist = list_delete_cell(rel->pathlist, - cell, prev); - else - prev = cell; - } - } + /* Regenerate paths with the current enforcement */ + set_plain_rel_pathlist(root, rel, rte); - /* then generate new paths if needed */ - if (phint->nworkers > 0) + /* Additional work to enforce parallel query execution */ + if (phint && phint->nworkers > 0) { /* Lower the priorities of non-parallel paths */ foreach (l, rel->pathlist) @@ -4490,15 +4464,6 @@ pg_hint_plan_set_rel_pathlist(PlannerInfo * root, RelOptInfo *rel, } } - /* - * generate partial paths with enforcement, this is affected by - * scan method enforcement. Specifically, the cost of this partial - * seqscan path will be disabled_cost if seqscan is inhibited by - * hint or GUC parameters. - */ - Assert (rel->partial_pathlist == NIL); - create_plain_partial_paths(root, rel); - /* enforce number of workers if requested */ if (phint->force_parallel) { diff --git a/sql/ut-W.sql b/sql/ut-W.sql index d72c763..199b607 100644 --- a/sql/ut-W.sql +++ b/sql/ut-W.sql @@ -98,11 +98,11 @@ EXPLAIN (COSTS false) SELECT * FROM p1 join p2 on p1.id = p2.id; /*+Parallel(p1 8 hard) IndexScan(p2) */ EXPLAIN (COSTS false) SELECT * FROM p1 join p2 on p1.id = p2.id; --- seqscan doesn't harm parallelism +-- Parallel sequential scan /*+Parallel(p1 8 hard) SeqScan(p1) */ EXPLAIN (COSTS false) SELECT * FROM p1 join p2 on p1.id = p2.id; --- Index partial scan is not handled yet. +-- Parallel index scan /*+Parallel(p1 8 hard) IndexScan(p1) */ EXPLAIN (COSTS false) SELECT * FROM p1 join p2 on p1.id = p2.id; -- 2.11.0