ROLLBACK;
-- ===================================================================
--- test partition-wise-joins
+-- test partitionwise joins
-- ===================================================================
-SET enable_partition_wise_join=on;
+SET enable_partitionwise_join=on;
CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
CREATE TABLE fprt1_p1 (LIKE fprt1);
CREATE TABLE fprt1_p2 (LIKE fprt1);
400 | 400
(4 rows)
-RESET enable_partition_wise_join;
+RESET enable_partitionwise_join;
ROLLBACK;
-- ===================================================================
--- test partition-wise-joins
+-- test partitionwise joins
-- ===================================================================
-SET enable_partition_wise_join=on;
+SET enable_partitionwise_join=on;
CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
CREATE TABLE fprt1_p1 (LIKE fprt1);
SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2;
SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2;
-RESET enable_partition_wise_join;
+RESET enable_partitionwise_join;
</listitem>
</varlistentry>
- <varlistentry id="guc-enable-partition-wise-join" xreflabel="enable_partition_wise_join">
- <term><varname>enable_partition_wise_join</varname> (<type>boolean</type>)
+ <varlistentry id="guc-enable-partitionwise-join" xreflabel="enable_partitionwise_join">
+ <term><varname>enable_partitionwise_join</varname> (<type>boolean</type>)
<indexterm>
- <primary><varname>enable_partition_wise_join</varname> configuration parameter</primary>
+ <primary><varname>enable_partitionwise_join</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
- Enables or disables the query planner's use of partition-wise join,
+ Enables or disables the query planner's use of partitionwise join,
which allows a join between partitioned tables to be performed by
- joining the matching partitions. Partition-wise join currently applies
+ joining the matching partitions. Partitionwise join currently applies
only when the join conditions include all the partition keys, which
must be of the same data type and have exactly matching sets of child
- partitions. Because partition-wise join planning can use significantly
+ partitions. Because partitionwise join planning can use significantly
more CPU time and memory during planning, the default is
<literal>off</literal>.
</para>
pushed below the Gather (and costing them accurately) is likely to keep us
busy for a long time to come.
-Partition-wise joins
---------------------
+Partitionwise joins
+-------------------
A join between two similarly partitioned tables can be broken down into joins
between their matching partitions if there exists an equi-join condition
between the partition keys of the joining tables. The equi-join between
join between similarly partitioned tables having equi-join condition between
their partition keys to be broken down into N-way joins between their matching
partitions. This technique of breaking down a join between partitioned tables
-into joins between their partitions is called partition-wise join. We will use
+into joins between their partitions is called partitionwise join. We will use
term "partitioned relation" for either a partitioned table or a join between
compatibly partitioned tables.
/* Keep searching if join order is not valid */
if (joinrel)
{
- /* Create paths for partition-wise joins. */
- generate_partition_wise_join_paths(root, joinrel);
+ /* Create paths for partitionwise joins. */
+ generate_partitionwise_join_paths(root, joinrel);
/* Create GatherPaths for any useful partial paths for rel */
generate_gather_paths(root, joinrel);
/*
* We need attr_needed data for building targetlist of a join
* relation representing join between matching partitions for
- * partition-wise join. A given attribute of a child will be
+ * partitionwise join. A given attribute of a child will be
* needed in the same highest joinrel where the corresponding
* attribute of parent is needed. Hence it suffices to use the
* same Relids set for parent and child.
/*
* Copy/Modify targetlist. Even if this child is deemed empty, we need
* its targetlist in case it falls on nullable side in a child-join
- * because of partition-wise join.
+ * because of partitionwise join.
*
* NB: the resulting childrel->reltarget->exprs may contain arbitrary
* expressions, which otherwise would not occur in a rel's targetlist.
join_search_one_level(root, lev);
/*
- * Run generate_partition_wise_join_paths() and
+ * Run generate_partitionwise_join_paths() and
* generate_gather_paths() for each just-processed joinrel. We could
* not do this earlier because both regular and partial paths can get
* added to a particular joinrel at multiple times within
{
rel = (RelOptInfo *) lfirst(lc);
- /* Create paths for partition-wise joins. */
- generate_partition_wise_join_paths(root, rel);
+ /* Create paths for partitionwise joins. */
+ generate_partitionwise_join_paths(root, rel);
/* Create GatherPaths for any useful partial paths for rel */
generate_gather_paths(root, rel);
}
/*
- * generate_partition_wise_join_paths
- * Create paths representing partition-wise join for given partitioned
+ * generate_partitionwise_join_paths
+ * Create paths representing partitionwise join for given partitioned
* join relation.
*
* This must not be called until after we are done adding paths for all
* generated here has a reference.
*/
void
-generate_partition_wise_join_paths(PlannerInfo *root, RelOptInfo *rel)
+generate_partitionwise_join_paths(PlannerInfo *root, RelOptInfo *rel)
{
List *live_children = NIL;
int cnt_parts;
Assert(child_rel != NULL);
- /* Add partition-wise join paths for partitioned child-joins. */
- generate_partition_wise_join_paths(root, child_rel);
+ /* Add partitionwise join paths for partitioned child-joins. */
+ generate_partitionwise_join_paths(root, child_rel);
/* Dummy children will not be scanned, so ignore those. */
if (IS_DUMMY_REL(child_rel))
bool enable_mergejoin = true;
bool enable_hashjoin = true;
bool enable_gathermerge = true;
-bool enable_partition_wise_join = false;
+bool enable_partitionwise_join = false;
bool enable_parallel_append = true;
bool enable_parallel_hash = true;
static void populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
RelOptInfo *rel2, RelOptInfo *joinrel,
SpecialJoinInfo *sjinfo, List *restrictlist);
-static void try_partition_wise_join(PlannerInfo *root, RelOptInfo *rel1,
+static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1,
RelOptInfo *rel2, RelOptInfo *joinrel,
SpecialJoinInfo *parent_sjinfo,
List *parent_restrictlist);
break;
}
- /* Apply partition-wise join technique, if possible. */
- try_partition_wise_join(root, rel1, rel2, joinrel, sjinfo, restrictlist);
+ /* Apply partitionwise join technique, if possible. */
+ try_partitionwise_join(root, rel1, rel2, joinrel, sjinfo, restrictlist);
}
/*
* Assess whether join between given two partitioned relations can be broken
* down into joins between matching partitions; a technique called
- * "partition-wise join"
+ * "partitionwise join"
*
- * Partition-wise join is possible when a. Joining relations have same
+ * Partitionwise join is possible when a. Joining relations have same
* partitioning scheme b. There exists an equi-join between the partition keys
* of the two relations.
*
- * Partition-wise join is planned as follows (details: optimizer/README.)
+ * Partitionwise join is planned as follows (details: optimizer/README.)
*
* 1. Create the RelOptInfos for joins between matching partitions i.e
* child-joins and add paths to them.
*
* 2. Construct Append or MergeAppend paths across the set of child joins.
- * This second phase is implemented by generate_partition_wise_join_paths().
+ * This second phase is implemented by generate_partitionwise_join_paths().
*
* The RelOptInfo, SpecialJoinInfo and restrictlist for each child join are
* obtained by translating the respective parent join structures.
*/
static void
-try_partition_wise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
+try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
RelOptInfo *joinrel, SpecialJoinInfo *parent_sjinfo,
List *parent_restrictlist)
{
joinrel->part_scheme == rel2->part_scheme);
/*
- * Since we allow partition-wise join only when the partition bounds of
+ * Since we allow partitionwise join only when the partition bounds of
* the joining relations exactly match, the partition bounds of the join
* should match those of the joining relations.
*/
/*
* Only clauses referencing the partition keys are useful for
- * partition-wise join.
+ * partitionwise join.
*/
ipk1 = match_expr_to_partition_keys(expr1, rel1, strict_op);
if (ipk1 < 0)
/*
* If the clause refers to keys at different ordinal positions, it can
- * not be used for partition-wise join.
+ * not be used for partitionwise join.
*/
if (ipk1 != ipk2)
continue;
/*
- * The clause allows partition-wise join if only it uses the same
+ * The clause allows partitionwise join if only it uses the same
* operator family as that specified by the partition key.
*/
if (rel1->part_scheme->strategy == PARTITION_STRATEGY_HASH)
int cnt;
PartitionScheme part_scheme;
- /* Nothing to do if partition-wise join technique is disabled. */
- if (!enable_partition_wise_join)
+ /* Nothing to do if partitionwise join technique is disabled. */
+ if (!enable_partitionwise_join)
{
Assert(!IS_PARTITIONED_REL(joinrel));
return;
}
/*
- * We can only consider this join as an input to further partition-wise
+ * We can only consider this join as an input to further partitionwise
* joins if (a) the input relations are partitioned, (b) the partition
* schemes match, and (c) we can identify an equi-join between the
* partition keys. Note that if it were possible for
NULL, NULL, NULL
},
{
- {"enable_partition_wise_join", PGC_USERSET, QUERY_TUNING_METHOD,
- gettext_noop("Enables partition-wise join."),
+ {"enable_partitionwise_join", PGC_USERSET, QUERY_TUNING_METHOD,
+ gettext_noop("Enables partitionwise join."),
NULL
},
- &enable_partition_wise_join,
+ &enable_partitionwise_join,
false,
NULL, NULL, NULL
},
#enable_seqscan = on
#enable_sort = on
#enable_tidscan = on
-#enable_partition_wise_join = off
+#enable_partitionwise_join = off
#enable_parallel_hash = on
# - Planner Cost Constants -
extern PGDLLIMPORT bool enable_mergejoin;
extern PGDLLIMPORT bool enable_hashjoin;
extern PGDLLIMPORT bool enable_gathermerge;
-extern PGDLLIMPORT bool enable_partition_wise_join;
+extern PGDLLIMPORT bool enable_partitionwise_join;
extern PGDLLIMPORT bool enable_parallel_append;
extern PGDLLIMPORT bool enable_parallel_hash;
extern PGDLLIMPORT int constraint_exclusion;
double index_pages, int max_workers);
extern void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel,
Path *bitmapqual);
-extern void generate_partition_wise_join_paths(PlannerInfo *root,
+extern void generate_partitionwise_join_paths(PlannerInfo *root,
RelOptInfo *rel);
#ifdef OPTIMIZER_DEBUG
--
-- PARTITION_JOIN
--- Test partition-wise join between partitioned tables
+-- Test partitionwise join between partitioned tables
--
--- Enable partition-wise join, which by default is disabled.
-SET enable_partition_wise_join to true;
+-- Enable partitionwise join, which by default is disabled.
+SET enable_partitionwise_join to true;
--
-- partitioned by a single column
--
| | 525 | 0001
(16 rows)
--- lateral partition-wise join
+-- lateral partitionwise join
EXPLAIN (COSTS OFF)
SELECT * FROM prt1_l t1 LEFT JOIN LATERAL
(SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss
CREATE TABLE prt4_n_p3 PARTITION OF prt4_n FOR VALUES FROM (500) TO (600);
INSERT INTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
ANALYZE prt4_n;
--- partition-wise join can not be applied if the partition ranges differ
+-- partitionwise join can not be applied if the partition ranges differ
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a;
QUERY PLAN
-> Seq Scan on prt2_p3 t3_2
(23 rows)
--- partition-wise join can not be applied if there are no equi-join conditions
+-- partitionwise join can not be applied if there are no equi-join conditions
-- between partition keys
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b);
(12 rows)
-- equi-join with join condition on partial keys does not qualify for
--- partition-wise join
+-- partitionwise join
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2;
QUERY PLAN
(11 rows)
-- equi-join between out-of-order partition key columns does not qualify for
--- partition-wise join
+-- partitionwise join
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b;
QUERY PLAN
-> Seq Scan on prt2_m_p3 t2_2
(11 rows)
--- equi-join between non-key columns does not qualify for partition-wise join
+-- equi-join between non-key columns does not qualify for partitionwise join
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c;
QUERY PLAN
-> Seq Scan on prt2_m_p3 t2_2
(11 rows)
--- partition-wise join can not be applied between tables with different
+-- partitionwise join can not be applied between tables with different
-- partition lists
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c);
-> Seq Scan on prt1_n_p2 t1_1
(16 rows)
--- partition-wise join can not be applied for a join between list and range
+-- partitionwise join can not be applied for a join between list and range
-- partitioned table
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c);
-- This is to record the prevailing planner enable_foo settings during
-- a regression test run.
select name, setting from pg_settings where name like 'enable%';
- name | setting
-----------------------------+---------
- enable_bitmapscan | on
- enable_gathermerge | on
- enable_hashagg | on
- enable_hashjoin | on
- enable_indexonlyscan | on
- enable_indexscan | on
- enable_material | on
- enable_mergejoin | on
- enable_nestloop | on
- enable_parallel_append | on
- enable_parallel_hash | on
- enable_partition_wise_join | off
- enable_seqscan | on
- enable_sort | on
- enable_tidscan | on
+ name | setting
+---------------------------+---------
+ enable_bitmapscan | on
+ enable_gathermerge | on
+ enable_hashagg | on
+ enable_hashjoin | on
+ enable_indexonlyscan | on
+ enable_indexscan | on
+ enable_material | on
+ enable_mergejoin | on
+ enable_nestloop | on
+ enable_parallel_append | on
+ enable_parallel_hash | on
+ enable_partitionwise_join | off
+ enable_seqscan | on
+ enable_sort | on
+ enable_tidscan | on
(15 rows)
-- Test that the pg_timezone_names and pg_timezone_abbrevs views are
--
-- PARTITION_JOIN
--- Test partition-wise join between partitioned tables
+-- Test partitionwise join between partitioned tables
--
--- Enable partition-wise join, which by default is disabled.
-SET enable_partition_wise_join to true;
+-- Enable partitionwise join, which by default is disabled.
+SET enable_partitionwise_join to true;
--
-- partitioned by a single column
SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE prt2_l.a = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c) ORDER BY t1.a, t2.b;
SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE prt2_l.a = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c) ORDER BY t1.a, t2.b;
--- lateral partition-wise join
+-- lateral partitionwise join
EXPLAIN (COSTS OFF)
SELECT * FROM prt1_l t1 LEFT JOIN LATERAL
(SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss
INSERT INTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i;
ANALYZE prt4_n;
--- partition-wise join can not be applied if the partition ranges differ
+-- partitionwise join can not be applied if the partition ranges differ
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a;
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2, prt2 t3 WHERE t1.a = t2.a and t1.a = t3.b;
--- partition-wise join can not be applied if there are no equi-join conditions
+-- partitionwise join can not be applied if there are no equi-join conditions
-- between partition keys
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b);
-- equi-join with join condition on partial keys does not qualify for
--- partition-wise join
+-- partitionwise join
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2;
-- equi-join between out-of-order partition key columns does not qualify for
--- partition-wise join
+-- partitionwise join
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b;
--- equi-join between non-key columns does not qualify for partition-wise join
+-- equi-join between non-key columns does not qualify for partitionwise join
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c;
--- partition-wise join can not be applied between tables with different
+-- partitionwise join can not be applied between tables with different
-- partition lists
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c);
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 JOIN prt2_n t2 ON (t1.c = t2.c) JOIN plt1 t3 ON (t1.c = t3.c);
--- partition-wise join can not be applied for a join between list and range
+-- partitionwise join can not be applied for a join between list and range
-- partitioned table
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c);