From 377be46520719e4181e345dc538bb8301b72be19 Mon Sep 17 00:00:00 2001 From: yuzupy Date: Wed, 7 Nov 2018 11:42:15 +0900 Subject: [PATCH 1/3] Modify hypo_get_qual_for_range() for hypothetical default partition --- hypopg_table.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/hypopg_table.c b/hypopg_table.c index 9188a75..297baae 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -2471,25 +2471,17 @@ hypo_get_qual_for_range(hypoTable *parent, PartitionBoundSpec *spec, bool for_de for (i = 0; i < nparts; i++) { - Oid inhrelid = inhoids[i]; //is this a parent oid or dummy child oid? - HeapTuple tuple; - Datum datum; - bool isnull; + Oid inhrelid = inhoids[i]; + hypoTable *part; PartitionBoundSpec *bspec; - elog(NOTICE,"inhrelid : %u",inhrelid); + /* + * get each partition's boundspec from hypoTable entry + * instead of catalog + */ + part = hypo_find_table(inhrelid, false); + bspec = part->boundspec; - tuple = SearchSysCache1(RELOID, inhrelid); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for relation %u", inhrelid); - - datum = SysCacheGetAttr(RELOID, tuple, - Anum_pg_class_relpartbound, - &isnull); - - Assert(!isnull); - bspec = (PartitionBoundSpec *) - stringToNode(TextDatumGetCString(datum)); if (!IsA(bspec, PartitionBoundSpec)) elog(ERROR, "expected PartitionBoundSpec"); @@ -2507,7 +2499,6 @@ hypo_get_qual_for_range(hypoTable *parent, PartitionBoundSpec *spec, bool for_de ? makeBoolExpr(AND_EXPR, part_qual, -1) : linitial(part_qual)); } - ReleaseSysCache(tuple); } if (or_expr_args != NIL) From 567d56d6abe1c1c6692af36b272c528564186b23 Mon Sep 17 00:00:00 2001 From: yuzupy Date: Wed, 7 Nov 2018 12:10:45 +0900 Subject: [PATCH 2/3] Modify a way of estimate hypothetical partition's pages/tuples --- hypopg_analyze.c | 2 ++ hypopg_table.c | 55 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/hypopg_analyze.c b/hypopg_analyze.c index 3702b95..384eb14 100644 --- a/hypopg_analyze.c +++ b/hypopg_analyze.c @@ -317,6 +317,8 @@ static void hypo_do_analyze_partition(Relation onerel, Relation pgstats, * partition * */ totalrows = SPI_processed * 100 / fraction; + part->tuples = (int) totalrows; + part->set_tuples = true; /* * Compute the statistics. Temporary results during the calculations for diff --git a/hypopg_table.c b/hypopg_table.c index 297baae..91561d1 100644 --- a/hypopg_table.c +++ b/hypopg_table.c @@ -2007,9 +2007,12 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, } /* - * If this rel is a partition, we will estimate pages and tuples according - * to its partition bound and root table's pages and tuples. + * If this rel is a partition, we set rel->pages and rel->tuples. * + * When hypoTable->set_tuples is true, pages and tuples are set + * according to hypoTable->tuples. Otherwise, we will estimate pages + * and tuples here according to its partition bound and root table's + * pages and tuples as follows: * In the case of RANGE/LIST partitioning, we will compute selectivity * according to the partition constraints including its ancestors'. * On the other hand, in the case of HASH partitioning, we will multiply @@ -2042,18 +2045,6 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, return; } - /* - * hypo_clauselist_selectivity will retrieve the constraints for this - * partition and all its ancestors - */ - selectivity = hypo_clauselist_selectivity(root, rel, NIL, - part->rootid, part->parentid); - - elog(DEBUG1, "hypopg: selectivity for partition \"%s\": %lf", - hypo_find_table(linitial_oid(planner_rt_fetch(rel->relid, - root)->values_lists), false)->tablename, - selectivity); - /* * Selectivity for hash partitions cannot be done using the standard * clauselist_selectivity(), because the underlying constraint is using @@ -2078,10 +2069,38 @@ hypo_injectHypotheticalPartitioning(PlannerInfo *root, elog(DEBUG1, "hypopg: total modulus for partition %s: %d", part->tablename, total_modulus); - /* compute pages and tuples using selectivity and total_modulus */ - pages = ceil(rel->pages * selectivity / total_modulus); - rel->pages = (BlockNumber) pages; - rel->tuples = clamp_row_est(rel->tuples * selectivity / total_modulus); + + if (part->set_tuples) + { + /* + * pages and tuples are set according to part->tuples got by + * hypopg_analyze function. But we need compute them again + * using total_modulus for hash partitioning, since hypopg_analyze + * cannot run on hash partitioning + */ + pages = ceil(rel->pages * part->tuples / rel->tuples / total_modulus); + rel->pages = (BlockNumber) pages; + rel->tuples = clamp_row_est(part->tuples / total_modulus); + } + else + { + /* + * hypo_clauselist_selectivity will retrieve the constraints for this + * partition and all its ancestors + */ + selectivity = hypo_clauselist_selectivity(root, rel, NIL, + part->rootid, part->parentid); + + elog(DEBUG1, "hypopg: selectivity for partition \"%s\": %lf", + hypo_find_table(linitial_oid(planner_rt_fetch(rel->relid, + root)->values_lists), false)->tablename, + selectivity); + + /* compute pages and tuples using selectivity and total_modulus */ + pages = ceil(rel->pages * selectivity / total_modulus); + rel->pages = (BlockNumber) pages; + rel->tuples = clamp_row_est(rel->tuples * selectivity / total_modulus); + } } /* From ffcd3c7cc005a759478a863d46b4fbf84a5aefdf Mon Sep 17 00:00:00 2001 From: yuzupy Date: Wed, 7 Nov 2018 13:38:20 +0900 Subject: [PATCH 3/3] Add default partition tests to the regression test --- expected/hypo_table.out | 176 ++++++++++++++++++++++++++++++++++------ test/sql/hypo_table.sql | 22 ++++- 2 files changed, 170 insertions(+), 28 deletions(-) diff --git a/expected/hypo_table.out b/expected/hypo_table.out index 0e58990..79f5deb 100644 --- a/expected/hypo_table.out +++ b/expected/hypo_table.out @@ -42,6 +42,7 @@ CREATE TABLE part_multi_2_q1 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-0 CREATE TABLE part_multi_2_q2 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); CREATE TABLE part_multi_2_q3 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); CREATE TABLE part_multi_2_q4 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$); +CREATE TABLE part_multi_2_def PARTITION OF part_multi_2 DEFAULT; CREATE TABLE part_multi_1 PARTITION OF part_multi FOR VALUES IN (1) PARTITION BY RANGE(dt); CREATE TABLE part_multi_1_q2 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); CREATE TABLE part_multi_1_q3 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); @@ -49,12 +50,20 @@ CREATE TABLE part_multi_1_q4 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-1 CREATE TABLE part_multi_1_q1 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$) PARTITION BY RANGE (dt); CREATE TABLE part_multi_1_q1_b PARTITION OF part_multi_1_q1 FOR VALUES FROM ($$2015-02-01$$) TO ($$2015-04-01$$); CREATE TABLE part_multi_1_q1_a PARTITION OF part_multi_1_q1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-02-01$$); +CREATE TABLE part_multi_1_def PARTITION OF part_multi_1 DEFAULT; CREATE TABLE part_multi_3 PARTITION OF part_multi FOR VALUES IN (3) PARTITION BY RANGE(dt); CREATE TABLE part_multi_3_q1 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$); CREATE TABLE part_multi_3_q2 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); CREATE TABLE part_multi_3_q3 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); CREATE TABLE part_multi_3_q4 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$); -INSERT INTO part_multi select (i%3)+1, '2015-01-01'::date + interval '1 day' * (i%365), 'val ' || i FROM generate_series(1,10000) i; +CREATE TABLE part_multi_3_def PARTITION OF part_multi_3 DEFAULT; +CREATE TABLE part_multi_def PARTITION OF part_multi DEFAULT PARTITION BY RANGE(dt); +CREATE TABLE part_multi_def_q1 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$); +CREATE TABLE part_multi_def_q2 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); +CREATE TABLE part_multi_def_q3 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); +CREATE TABLE part_multi_def_q4 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$); +CREATE TABLE part_multi_def_def PARTITION OF part_multi_def DEFAULT; +INSERT INTO part_multi select (i%4)+1, '2015-01-01'::date + interval '1 day' * (i%500), 'val ' || i FROM generate_series(1,50000) i; -- Hypothetical tables -- ------------------- -- 0. Dropping any hypothetical object @@ -197,7 +206,7 @@ SELECT tablename FROM hypopg_add_partition('hypo_part_hash_0', 'PARTITION OF hyp DROP TABLE IF EXISTS hypo_part_multi; NOTICE: table "hypo_part_multi" does not exist, skipping CREATE TABLE hypo_part_multi(dpt smallint, dt date, val text); -INSERT INTO hypo_part_multi select (i%3)+1, '2015-01-01'::date + interval '1 day' * (i%365), 'val ' || i FROM generate_series(1,10000) i; +INSERT INTO hypo_part_multi select (i%4)+1, '2015-01-01'::date + interval '1 day' * (i%500), 'val ' || i FROM generate_series(1,50000) i; SELECT * FROM hypopg_partition_table('hypo_part_multi', 'PARTITION BY LIST (dpt)'); hypopg_partition_table ------------------------ @@ -234,6 +243,12 @@ SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_q4', 'PARTITION OF hypo_part_multi_2_q4 (1 row) +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_def', 'PARTITION OF hypo_part_multi_2 DEFAULT'); + tablename +----------------------- + hypo_part_multi_2_def +(1 row) + SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1', 'PARTITION OF hypo_part_multi FOR VALUES IN (1)', 'PARTITION BY RANGE(dt)'); tablename ------------------- @@ -276,6 +291,12 @@ SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q1_a', 'PARTITION hypo_part_multi_1_q1_a (1 row) +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_def', 'PARTITION OF hypo_part_multi_1 DEFAULT'); + tablename +----------------------- + hypo_part_multi_1_def +(1 row) + SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3', 'PARTITION OF hypo_part_multi FOR VALUES IN (3)', 'PARTITION BY RANGE(dt)'); tablename ------------------- @@ -306,6 +327,48 @@ SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3_q4', 'PARTITION OF hypo_part_multi_3_q4 (1 row) +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3_def', 'PARTITION OF hypo_part_multi_3 DEFAULT'); + tablename +----------------------- + hypo_part_multi_3_def +(1 row) + +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def', 'PARTITION OF hypo_part_multi DEFAULT' ,'PARTITION BY RANGE(dt)'); + tablename +--------------------- + hypo_part_multi_def +(1 row) + +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q1', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)'); + tablename +------------------------ + hypo_part_multi_def_q1 +(1 row) + +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q2', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$)'); + tablename +------------------------ + hypo_part_multi_def_q2 +(1 row) + +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q3', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$)'); + tablename +------------------------ + hypo_part_multi_def_q3 +(1 row) + +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q4', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$)'); + tablename +------------------------ + hypo_part_multi_def_q4 +(1 row) + +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_def', 'PARTITION OF hypo_part_multi_def DEFAULT'); + tablename +------------------------- + hypo_part_multi_def_def +(1 row) + -- Maintenance -- ----------- VACUUM ANALYZE; @@ -376,6 +439,7 @@ FROM hypopg_table(); f | hypo_part_multi_2_q2 | f | t | | FOR VALUES FROM ('04-01-2015') TO ('07-01-2015') f | hypo_part_multi_2_q3 | f | t | | FOR VALUES FROM ('07-01-2015') TO ('10-01-2015') f | hypo_part_multi_2_q4 | f | t | | FOR VALUES FROM ('10-01-2015') TO ('01-01-2016') + f | hypo_part_multi_2_def | f | t | | DEFAULT f | hypo_part_multi_1 | f | t | PARTITION BY RANGE (dt) | FOR VALUES IN ('1') f | hypo_part_multi_1_q2 | f | t | | FOR VALUES FROM ('04-01-2015') TO ('07-01-2015') f | hypo_part_multi_1_q3 | f | t | | FOR VALUES FROM ('07-01-2015') TO ('10-01-2015') @@ -383,12 +447,20 @@ FROM hypopg_table(); f | hypo_part_multi_1_q1 | f | t | PARTITION BY RANGE (dt) | FOR VALUES FROM ('01-01-2015') TO ('04-01-2015') f | hypo_part_multi_1_q1_b | f | t | | FOR VALUES FROM ('02-01-2015') TO ('04-01-2015') f | hypo_part_multi_1_q1_a | f | t | | FOR VALUES FROM ('01-01-2015') TO ('02-01-2015') + f | hypo_part_multi_1_def | f | t | | DEFAULT f | hypo_part_multi_3 | f | t | PARTITION BY RANGE (dt) | FOR VALUES IN ('3') f | hypo_part_multi_3_q1 | f | t | | FOR VALUES FROM ('01-01-2015') TO ('04-01-2015') f | hypo_part_multi_3_q2 | f | t | | FOR VALUES FROM ('04-01-2015') TO ('07-01-2015') f | hypo_part_multi_3_q3 | f | t | | FOR VALUES FROM ('07-01-2015') TO ('10-01-2015') f | hypo_part_multi_3_q4 | f | t | | FOR VALUES FROM ('10-01-2015') TO ('01-01-2016') -(37 rows) + f | hypo_part_multi_3_def | f | t | | DEFAULT + f | hypo_part_multi_def | f | t | PARTITION BY RANGE (dt) | DEFAULT + f | hypo_part_multi_def_q1 | f | t | | FOR VALUES FROM ('01-01-2015') TO ('04-01-2015') + f | hypo_part_multi_def_q2 | f | t | | FOR VALUES FROM ('04-01-2015') TO ('07-01-2015') + f | hypo_part_multi_def_q3 | f | t | | FOR VALUES FROM ('07-01-2015') TO ('10-01-2015') + f | hypo_part_multi_def_q4 | f | t | | FOR VALUES FROM ('10-01-2015') TO ('01-01-2016') + f | hypo_part_multi_def_def | f | t | | DEFAULT +(46 rows) -- Test hypothetical partitioning behavior -- ======================================= @@ -529,27 +601,35 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_hash WHERE id < 15000; -- 4. Multi level range EXPLAIN (COSTS OFF) SELECT * FROM part_multi; - QUERY PLAN -------------------------------------- + QUERY PLAN +-------------------------------------- Append -> Seq Scan on part_multi_1_q1_a -> Seq Scan on part_multi_1_q1_b -> Seq Scan on part_multi_1_q2 -> Seq Scan on part_multi_1_q3 -> Seq Scan on part_multi_1_q4 + -> Seq Scan on part_multi_1_def -> Seq Scan on part_multi_2_q1 -> Seq Scan on part_multi_2_q2 -> Seq Scan on part_multi_2_q3 -> Seq Scan on part_multi_2_q4 + -> Seq Scan on part_multi_2_def -> Seq Scan on part_multi_3_q1 -> Seq Scan on part_multi_3_q2 -> Seq Scan on part_multi_3_q3 -> Seq Scan on part_multi_3_q4 -(14 rows) + -> Seq Scan on part_multi_3_def + -> Seq Scan on part_multi_def_q1 + -> Seq Scan on part_multi_def_q2 + -> Seq Scan on part_multi_def_q3 + -> Seq Scan on part_multi_def_q4 + -> Seq Scan on part_multi_def_def +(22 rows) EXPLAIN (COSTS OFF) SELECT * FROM part_multi WHERE dpt = 2; - QUERY PLAN ------------------------------------ + QUERY PLAN +------------------------------------ Append -> Seq Scan on part_multi_2_q1 Filter: (dpt = 2) @@ -559,7 +639,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_multi WHERE dpt = 2; Filter: (dpt = 2) -> Seq Scan on part_multi_2_q4 Filter: (dpt = 2) -(9 rows) + -> Seq Scan on part_multi_2_def + Filter: (dpt = 2) +(11 rows) EXPLAIN (COSTS OFF) SELECT * FROM part_multi WHERE dt >= '2015-01-05' AND dt < '2015-01-10'; QUERY PLAN @@ -567,11 +649,21 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_multi WHERE dt >= '2015-01-05' AND dt < ' Append -> Seq Scan on part_multi_1_q1_a Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on part_multi_1_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) -> Seq Scan on part_multi_2_q1 Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on part_multi_2_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) -> Seq Scan on part_multi_3_q1 Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) -(7 rows) + -> Seq Scan on part_multi_3_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on part_multi_def_q1 + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on part_multi_def_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) +(17 rows) -- Hypothetical tables -- ------------------- @@ -708,27 +800,35 @@ EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_hash WHERE id < 15000; -- 4. Multi level range EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi; - QUERY PLAN ----------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------- Append -> Seq Scan on hypo_part_multi hypo_part_multi_1_q1_a -> Seq Scan on hypo_part_multi hypo_part_multi_1_q1_b -> Seq Scan on hypo_part_multi hypo_part_multi_1_q2 -> Seq Scan on hypo_part_multi hypo_part_multi_1_q3 -> Seq Scan on hypo_part_multi hypo_part_multi_1_q4 + -> Seq Scan on hypo_part_multi hypo_part_multi_1_def -> Seq Scan on hypo_part_multi hypo_part_multi_2_q1 -> Seq Scan on hypo_part_multi hypo_part_multi_2_q2 -> Seq Scan on hypo_part_multi hypo_part_multi_2_q3 -> Seq Scan on hypo_part_multi hypo_part_multi_2_q4 + -> Seq Scan on hypo_part_multi hypo_part_multi_2_def -> Seq Scan on hypo_part_multi hypo_part_multi_3_q1 -> Seq Scan on hypo_part_multi hypo_part_multi_3_q2 -> Seq Scan on hypo_part_multi hypo_part_multi_3_q3 -> Seq Scan on hypo_part_multi hypo_part_multi_3_q4 -(14 rows) + -> Seq Scan on hypo_part_multi hypo_part_multi_3_def + -> Seq Scan on hypo_part_multi hypo_part_multi_def_q1 + -> Seq Scan on hypo_part_multi hypo_part_multi_def_q2 + -> Seq Scan on hypo_part_multi hypo_part_multi_def_q3 + -> Seq Scan on hypo_part_multi hypo_part_multi_def_q4 + -> Seq Scan on hypo_part_multi hypo_part_multi_def_def +(22 rows) EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi WHERE dpt = 2; - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------- Append -> Seq Scan on hypo_part_multi hypo_part_multi_2_q1 Filter: (dpt = 2) @@ -738,7 +838,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi WHERE dpt = 2; Filter: (dpt = 2) -> Seq Scan on hypo_part_multi hypo_part_multi_2_q4 Filter: (dpt = 2) -(9 rows) + -> Seq Scan on hypo_part_multi hypo_part_multi_2_def + Filter: (dpt = 2) +(11 rows) EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi WHERE dt >= '2015-01-05' AND dt < '2015-01-10'; QUERY PLAN @@ -746,11 +848,21 @@ EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi WHERE dt >= '2015-01-05' AND d Append -> Seq Scan on hypo_part_multi hypo_part_multi_1_q1_a Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on hypo_part_multi hypo_part_multi_1_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) -> Seq Scan on hypo_part_multi hypo_part_multi_2_q1 Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on hypo_part_multi hypo_part_multi_2_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) -> Seq Scan on hypo_part_multi hypo_part_multi_3_q1 Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) -(7 rows) + -> Seq Scan on hypo_part_multi hypo_part_multi_3_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on hypo_part_multi hypo_part_multi_def_q1 + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) + -> Seq Scan on hypo_part_multi hypo_part_multi_def_def + Filter: ((dt >= '01-05-2015'::date) AND (dt < '01-10-2015'::date)) +(17 rows) -- Join queries -- ------------ @@ -822,8 +934,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_hash t1, part_hash t2 WHERE t1.id = t2.id (25 rows) EXPLAIN (COSTS OFF) SELECT * FROM part_multi t1, part_multi t2 WHERE t1.dpt = t2.dpt and t1.dpt = 2; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +----------------------------------------------------- Nested Loop -> Append -> Seq Scan on part_multi_2_q1 t1 @@ -834,6 +946,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_multi t1, part_multi t2 WHERE t1.dpt = t2 Filter: (dpt = 2) -> Seq Scan on part_multi_2_q4 t1_3 Filter: (dpt = 2) + -> Seq Scan on part_multi_2_def t1_4 + Filter: (dpt = 2) -> Materialize -> Append -> Seq Scan on part_multi_2_q1 t2 @@ -844,7 +958,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_multi t1, part_multi t2 WHERE t1.dpt = t2 Filter: (dpt = 2) -> Seq Scan on part_multi_2_q4 t2_3 Filter: (dpt = 2) -(20 rows) + -> Seq Scan on part_multi_2_def t2_4 + Filter: (dpt = 2) +(24 rows) -- 2. Hypothetical tables EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_range t1, hypo_part_range t2 WHERE t1.id = t2.id and t1.id < 15000; @@ -912,8 +1028,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_hash t1, hypo_part_hash t2 WHERE t1. (25 rows) EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi t1, hypo_part_multi t2 WHERE t1.dpt = t2.dpt and t1.dpt = 2; - QUERY PLAN ----------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------- Nested Loop -> Append -> Seq Scan on hypo_part_multi hypo_part_multi_2_q1 @@ -924,6 +1040,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi t1, hypo_part_multi t2 WHERE t Filter: (dpt = 2) -> Seq Scan on hypo_part_multi hypo_part_multi_2_q4 Filter: (dpt = 2) + -> Seq Scan on hypo_part_multi hypo_part_multi_2_def + Filter: (dpt = 2) -> Materialize -> Append -> Seq Scan on hypo_part_multi hypo_part_multi_2_q1_1 @@ -934,7 +1052,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM hypo_part_multi t1, hypo_part_multi t2 WHERE t Filter: (dpt = 2) -> Seq Scan on hypo_part_multi hypo_part_multi_2_q4_1 Filter: (dpt = 2) -(20 rows) + -> Seq Scan on hypo_part_multi hypo_part_multi_2_def_1 + Filter: (dpt = 2) +(24 rows) -- 3. Real tables and hypothetical tables EXPLAIN (COSTS OFF) SELECT * FROM part_range t1, hypo_part_range t2 WHERE t1.id = t2.id and t1.id < 15000; @@ -1002,8 +1122,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_hash t1, hypo_part_hash t2 WHERE t1.id = (25 rows) EXPLAIN (COSTS OFF) SELECT * FROM part_multi t1, hypo_part_multi t2 WHERE t1.dpt = t2.dpt and t1.dpt = 2; - QUERY PLAN --------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------- Nested Loop -> Append -> Seq Scan on part_multi_2_q1 t1 @@ -1014,6 +1134,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_multi t1, hypo_part_multi t2 WHERE t1.dpt Filter: (dpt = 2) -> Seq Scan on part_multi_2_q4 t1_3 Filter: (dpt = 2) + -> Seq Scan on part_multi_2_def t1_4 + Filter: (dpt = 2) -> Materialize -> Append -> Seq Scan on hypo_part_multi hypo_part_multi_2_q1 @@ -1024,7 +1146,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_multi t1, hypo_part_multi t2 WHERE t1.dpt Filter: (dpt = 2) -> Seq Scan on hypo_part_multi hypo_part_multi_2_q4 Filter: (dpt = 2) -(20 rows) + -> Seq Scan on hypo_part_multi hypo_part_multi_2_def + Filter: (dpt = 2) +(24 rows) -- Partitionwise joins -- ------------------- diff --git a/test/sql/hypo_table.sql b/test/sql/hypo_table.sql index 845e026..853bed9 100644 --- a/test/sql/hypo_table.sql +++ b/test/sql/hypo_table.sql @@ -39,6 +39,7 @@ CREATE TABLE part_multi_2_q1 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-0 CREATE TABLE part_multi_2_q2 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); CREATE TABLE part_multi_2_q3 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); CREATE TABLE part_multi_2_q4 PARTITION OF part_multi_2 FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$); +CREATE TABLE part_multi_2_def PARTITION OF part_multi_2 DEFAULT; CREATE TABLE part_multi_1 PARTITION OF part_multi FOR VALUES IN (1) PARTITION BY RANGE(dt); CREATE TABLE part_multi_1_q2 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); CREATE TABLE part_multi_1_q3 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); @@ -46,12 +47,20 @@ CREATE TABLE part_multi_1_q4 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-1 CREATE TABLE part_multi_1_q1 PARTITION OF part_multi_1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$) PARTITION BY RANGE (dt); CREATE TABLE part_multi_1_q1_b PARTITION OF part_multi_1_q1 FOR VALUES FROM ($$2015-02-01$$) TO ($$2015-04-01$$); CREATE TABLE part_multi_1_q1_a PARTITION OF part_multi_1_q1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-02-01$$); +CREATE TABLE part_multi_1_def PARTITION OF part_multi_1 DEFAULT; CREATE TABLE part_multi_3 PARTITION OF part_multi FOR VALUES IN (3) PARTITION BY RANGE(dt); CREATE TABLE part_multi_3_q1 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$); CREATE TABLE part_multi_3_q2 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); CREATE TABLE part_multi_3_q3 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); CREATE TABLE part_multi_3_q4 PARTITION OF part_multi_3 FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$); -INSERT INTO part_multi select (i%3)+1, '2015-01-01'::date + interval '1 day' * (i%365), 'val ' || i FROM generate_series(1,10000) i; +CREATE TABLE part_multi_3_def PARTITION OF part_multi_3 DEFAULT; +CREATE TABLE part_multi_def PARTITION OF part_multi DEFAULT PARTITION BY RANGE(dt); +CREATE TABLE part_multi_def_q1 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$); +CREATE TABLE part_multi_def_q2 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$); +CREATE TABLE part_multi_def_q3 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$); +CREATE TABLE part_multi_def_q4 PARTITION OF part_multi_def FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$); +CREATE TABLE part_multi_def_def PARTITION OF part_multi_def DEFAULT; +INSERT INTO part_multi select (i%4)+1, '2015-01-01'::date + interval '1 day' * (i%500), 'val ' || i FROM generate_series(1,50000) i; -- Hypothetical tables -- ------------------- @@ -91,13 +100,14 @@ SELECT tablename FROM hypopg_add_partition('hypo_part_hash_0', 'PARTITION OF hyp -- 4. Multi level range DROP TABLE IF EXISTS hypo_part_multi; CREATE TABLE hypo_part_multi(dpt smallint, dt date, val text); -INSERT INTO hypo_part_multi select (i%3)+1, '2015-01-01'::date + interval '1 day' * (i%365), 'val ' || i FROM generate_series(1,10000) i; +INSERT INTO hypo_part_multi select (i%4)+1, '2015-01-01'::date + interval '1 day' * (i%500), 'val ' || i FROM generate_series(1,50000) i; SELECT * FROM hypopg_partition_table('hypo_part_multi', 'PARTITION BY LIST (dpt)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2', 'PARTITION OF hypo_part_multi FOR VALUES IN (2)', 'PARTITION BY RANGE(dt)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_q1', 'PARTITION OF hypo_part_multi_2 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_q2', 'PARTITION OF hypo_part_multi_2 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_q3', 'PARTITION OF hypo_part_multi_2 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_q4', 'PARTITION OF hypo_part_multi_2 FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_2_def', 'PARTITION OF hypo_part_multi_2 DEFAULT'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1', 'PARTITION OF hypo_part_multi FOR VALUES IN (1)', 'PARTITION BY RANGE(dt)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q2', 'PARTITION OF hypo_part_multi_1 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q3', 'PARTITION OF hypo_part_multi_1 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$)'); @@ -105,11 +115,19 @@ SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q4', 'PARTITION OF SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q1', 'PARTITION OF hypo_part_multi_1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)','PARTITION BY RANGE (dt)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q1_b', 'PARTITION OF hypo_part_multi_1_q1 FOR VALUES FROM ($$2015-02-01$$) TO ($$2015-04-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_q1_a', 'PARTITION OF hypo_part_multi_1_q1 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-02-01$$)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_1_def', 'PARTITION OF hypo_part_multi_1 DEFAULT'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3', 'PARTITION OF hypo_part_multi FOR VALUES IN (3)', 'PARTITION BY RANGE(dt)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3_q1', 'PARTITION OF hypo_part_multi_3 FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3_q2', 'PARTITION OF hypo_part_multi_3 FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3_q3', 'PARTITION OF hypo_part_multi_3 FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$)'); SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3_q4', 'PARTITION OF hypo_part_multi_3 FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_3_def', 'PARTITION OF hypo_part_multi_3 DEFAULT'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def', 'PARTITION OF hypo_part_multi DEFAULT' ,'PARTITION BY RANGE(dt)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q1', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-01-01$$) TO ($$2015-04-01$$)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q2', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-04-01$$) TO ($$2015-07-01$$)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q3', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-07-01$$) TO ($$2015-10-01$$)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_q4', 'PARTITION OF hypo_part_multi_def FOR VALUES FROM ($$2015-10-01$$) TO ($$2016-01-01$$)'); +SELECT tablename FROM hypopg_add_partition('hypo_part_multi_def_def', 'PARTITION OF hypo_part_multi_def DEFAULT'); -- Maintenance -- -----------