Changeset: fb7ffb6bcd79 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=fb7ffb6bcd79 Modified Files: sql/server/rel_optimizer.c sql/test/merge-partitions/Tests/mergepart31.sql sql/test/merge-partitions/Tests/mergepart31.stable.out Branch: Oct2020 Log Message:
Updated child elimination optimization for range partitions with identical min and max values diffs (215 lines): diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c --- a/sql/server/rel_optimizer.c +++ b/sql/server/rel_optimizer.c @@ -9121,19 +9121,26 @@ rel_merge_table_rewrite(visitor *v, sql_ skip |= nskip; } } else { /* limit1 to limit2 (general case), limit2 is exclusive */ + bool max_differ_min = ATOMcmp(col->type.type->localtype, &rmin->data.val, &rmax->data.val) != 0; + if (lval) { if (next->flag == cmp_equal) { - skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, false, true) != 0 : - exp_range_overlap(rmin, rmax, lval, hval, false, true) == 0; + skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, false, max_differ_min) != 0 : + exp_range_overlap(rmin, rmax, lval, hval, false, max_differ_min) == 0; } else if (hval != lval) { /* For the between case */ comp_type higher = range2rcompare(next->flag); - skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, true) != 0 : - exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, true) == 0; + skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, max_differ_min) != 0 : + exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, max_differ_min) == 0; } else { switch (next->flag) { case cmp_gt: + skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) < 0 : VALcmp(&(lval->data), &(rmax->data)) >= 0; + break; case cmp_gte: - skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) < 0 : VALcmp(&(lval->data), &(rmax->data)) >= 0; + if (max_differ_min) + skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) < 0 : VALcmp(&(lval->data), &(rmax->data)) >= 0; + else + skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) <= 0 : VALcmp(&(lval->data), &(rmax->data)) > 0; break; case cmp_lt: skip |= next->anti ? VALcmp(&(rmin->data), &(lval->data)) < 0 : VALcmp(&(rmin->data), &(lval->data)) >= 0; @@ -9152,7 +9159,7 @@ rel_merge_table_rewrite(visitor *v, sql_ if (a->isnull) continue; - nskip &= exp_range_overlap(rmin, rmax, a, a, false, true) == 0; + nskip &= exp_range_overlap(rmin, rmax, a, a, false, max_differ_min) == 0; } skip |= nskip; } diff --git a/sql/test/merge-partitions/Tests/mergepart31.sql b/sql/test/merge-partitions/Tests/mergepart31.sql --- a/sql/test/merge-partitions/Tests/mergepart31.sql +++ b/sql/test/merge-partitions/Tests/mergepart31.sql @@ -123,4 +123,31 @@ plan select 1 from splitted2 where stamp select 1 from splitted2 where stamp in (8,9); --all children pruned -- empty +CREATE MERGE TABLE table1 (a int, b int) PARTITION BY RANGE ON (a); +CREATE TABLE another1 (a int, b int); +CREATE TABLE another2 (a int, b int); + +ALTER TABLE table1 ADD TABLE another1 AS PARTITION FROM 10 TO 10; +ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 11 TO 11; + +plan select 1 from table1 where a = 10; --only first child passes + +plan select 1 from table1 where a = 11; --only second child passes + +plan select 1 from table1 where a = 10 or a = 11; --nothing gets pruned + +plan select 1 from table1 where a >= 10; --nothing gets pruned + +plan select 1 from table1 where a > 10; --only second child passes + +plan select 1 from table1 where a <= 10; --only first child passes + +plan select 1 from table1 where a between 10 and 10; --only first child passes + +plan select 1 from table1 where a = 10 or b = 11; --nothing gets pruned + +plan select 1 from table1 where a not between 10 and 11; --all children pruned + +plan select 1 from table1 where a not between 10 and 10; --only second child passes + ROLLBACK; diff --git a/sql/test/merge-partitions/Tests/mergepart31.stable.out b/sql/test/merge-partitions/Tests/mergepart31.stable.out --- a/sql/test/merge-partitions/Tests/mergepart31.stable.out +++ b/sql/test/merge-partitions/Tests/mergepart31.stable.out @@ -598,6 +598,132 @@ project ( % %5 # name % tinyint # type % 1 # length +#CREATE MERGE TABLE table1 (a int) PARTITION BY RANGE ON (a); +#CREATE TABLE another1 (a int); +#CREATE TABLE another2 (a int); +#ALTER TABLE table1 ADD TABLE another1 AS PARTITION FROM 10 TO 10; +#ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 11 TO 11; +#plan select 1 from table1 where a = 10; --only first child passes +% .plan # table_name +% rel # name +% clob # type +% 47 # length +project ( +| select ( +| | table(sys.another1) [ "table1"."a" ] COUNT +| ) [ "table1"."a" = int "10" ] +) [ tinyint "1" ] +#plan select 1 from table1 where a = 11; --only second child passes +% .plan # table_name +% rel # name +% clob # type +% 47 # length +project ( +| select ( +| | table(sys.another2) [ "table1"."a" ] COUNT +| ) [ "table1"."a" = int "11" ] +) [ tinyint "1" ] +#plan select 1 from table1 where a = 10 or a = 11; --nothing gets pruned +% .plan # table_name +% rel # name +% clob # type +% 67 # length +union ( +| project ( +| | select ( +| | | table(sys.another1) [ "another1"."a" as "table1"."a" ] COUNT +| | ) [ "table1"."a" in (int "10", int "11") ] +| ) [ tinyint "1" ], +| project ( +| | select ( +| | | table(sys.another2) [ "another2"."a" as "table1"."a" ] COUNT +| | ) [ "table1"."a" in (int "10", int "11") ] +| ) [ tinyint "1" ] +) [ "%3"."%3" NOT NULL ] +#plan select 1 from table1 where a >= 10; --nothing gets pruned +% .plan # table_name +% rel # name +% clob # type +% 67 # length +union ( +| project ( +| | select ( +| | | table(sys.another1) [ "another1"."a" as "table1"."a" ] COUNT +| | ) [ "table1"."a" >= int "10" ] +| ) [ tinyint "1" ], +| project ( +| | select ( +| | | table(sys.another2) [ "another2"."a" as "table1"."a" ] COUNT +| | ) [ "table1"."a" >= int "10" ] +| ) [ tinyint "1" ] +) [ "%3"."%3" NOT NULL ] +#plan select 1 from table1 where a > 10; --only second child passes +% .plan # table_name +% rel # name +% clob # type +% 47 # length +project ( +| select ( +| | table(sys.another2) [ "table1"."a" ] COUNT +| ) [ "table1"."a" > int "10" ] +) [ tinyint "1" ] +#plan select 1 from table1 where a <= 10; --only first child passes +% .plan # table_name +% rel # name +% clob # type +% 47 # length +project ( +| select ( +| | table(sys.another1) [ "table1"."a" ] COUNT +| ) [ "table1"."a" <= int "10" ] +) [ tinyint "1" ] +#plan select 1 from table1 where a between 10 and 10; --only first child passes +% .plan # table_name +% rel # name +% clob # type +% 53 # length +project ( +| select ( +| | table(sys.another1) [ "table1"."a" ] COUNT +| ) [ int "10" <= "table1"."a" <= int "10" BETWEEN ] +) [ tinyint "1" ] +#plan select 1 from table1 where a = 10 or b = 11; --nothing gets pruned +% .plan # table_name +% rel # name +% clob # type +% 99 # length +union ( +| project ( +| | select ( +| | | table(sys.another1) [ "another1"."a" as "table1"."a", "another1"."b" as "table1"."b" ] COUNT +| | ) [ ("table1"."a" = int "10") or ("table1"."b" = int "11") ] +| ) [ tinyint "1" ], +| project ( +| | select ( +| | | table(sys.another2) [ "another2"."a" as "table1"."a", "another2"."b" as "table1"."b" ] COUNT +| | ) [ ("table1"."a" = int "10") or ("table1"."b" = int "11") ] +| ) [ tinyint "1" ] +) [ "%3"."%3" NOT NULL ] +#plan select 1 from table1 where a not between 10 and 11; --all children pruned +% .plan # table_name +% rel # name +% clob # type +% 23 # length +project ( +| select ( +| | [ boolean "true" ] +| ) [ boolean "false" ] +) [ tinyint "1" ] +#plan select 1 from table1 where a not between 10 and 10; --only second child passes +% .plan # table_name +% rel # name +% clob # type +% 57 # length +project ( +| select ( +| | table(sys.another2) [ "table1"."a" ] COUNT +| ) [ int "10" ! <= "table1"."a" ! <= int "10" BETWEEN ] +) [ tinyint "1" ] #ROLLBACK; # 11:53:07 > _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list