Commit 61bbabb2 authored by Igor Babaev's avatar Igor Babaev

Implemented condition pushdown into derived tables / views

with window functions (mdev-10855).

This patch just modified the function pushdown_cond_for_derived()
to support this feature.
Some test cases demonstrating this optimization were added to
derived_cond_pushdown.test.
parent c9981fbe
This diff is collapsed.
......@@ -1549,6 +1549,78 @@ eval explain format=json $q;
DROP VIEW v2;
DROP TABLE t1,t2;
--echo #
--echo # MDEV-10855: Pushdown into derived with window functions
--echo #
set @save_optimizer_switch= @@optimizer_switch;
set optimizer_switch='split_grouping_derived=off';
create table t1 (a int, c varchar(16));
insert into t1 values
(8,'aa'), (5,'cc'), (1,'bb'), (2,'aa'), (9,'cc'),
(7,'aa'), (2,'aa'), (7,'bb');
create table t2 (a int, b int, c varchar(16), index idx(a,c));
insert into t2 values
(7,10,'cc'), (1,20,'aa'), (2,23,'bb'), (7,18,'cc'), (1,30,'bb'),
(4,71,'xx'), (3,15,'aa'), (7,82,'bb'), (8,12,'dd'), (4,15,'aa'),
(11,33,'yy'), (10,42,'zz'), (4,53,'xx'), (10,17,'yy'), (7,12,'bb'),
(8,20,'dd'), (7,32,'bb'), (1,50,'aa'), (3,40,'bb'), (3,77,'aa');
let $q1=
select * from (select a, c, sum(b) over (partition by a,c) from t2) as t
where t.a > 2 and t.c in ('aa','bb','cc');
eval $no_pushdown $q1;
eval $q1;
eval explain $q1;
eval explain format=json $q1;
let $q2=
select * from
(
select 1 as n, a, c, sum(b) over (partition by a,c) as s from t2
union all
select 2 as n, a, c, sum(b) over (partition by a) as s from t2
) as t
where t.a > 2 and t.c in ('aa','bb','cc');
eval $no_pushdown $q2;
eval $q2;
eval explain $q2;
eval explain format=json $q2;
let $q3=
select *
from (select a, c, sum(b) over (partition by a,c) as s from t2) as t, t1
where t1.a=t.a and t1.c=t.c and t1.c in ('aa','bb','cc');
eval $no_pushdown $q3;
eval $q3;
eval explain $q3;
eval explain format=json $q3;
let $q4=
select * from
(
select 1 as n, a, c, sum(b) over (partition by a,c) as s from t2
union all
select 2 as n, a, c, sum(b) over (partition by a) as s from t2
union all
select 3 as n, a, c, sum(b) as s from t2 group by a
) as t
where t.a > 2 and t.c in ('aa','bb','cc');
eval $no_pushdown $q4;
eval $q4;
eval explain $q4;
eval explain format=json $q4;
drop table t1,t2;
set optimizer_switch= @save_optimizer_switch;
--echo #
--echo # MDEV-13369: Optimization for equi-joins of grouping derived tables
--echo # (Splitting derived tables / views with GROUP BY)
......@@ -1596,7 +1668,6 @@ insert into t3 values
(8,'aa'), (5,'cc'), (1,'bb'), (2,'aa'), (9,'cc'),
(7,'aa'), (2,'aa'), (7,'bb');
create table t4 (a int, b int, c varchar(16), index idx(a,c));
insert into t4 values
(7,10,'cc'), (1,20,'aa'), (2,23,'bb'), (7,18,'cc'), (1,30,'bb'),
......@@ -1604,7 +1675,6 @@ insert into t4 values
(11,33,'yy'), (10,42,'zz'), (4,53,'xx'), (10,17,'yy'), (7,12,'bb'),
(8,20,'dd'), (7,32,'bb'), (1,50,'aa'), (3,40,'bb'), (3,77,'aa');
let $q3=
select t3.a,t3.c,t.max,t.min
from t3 join
......
......@@ -1243,14 +1243,50 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
st_select_lex *save_curr_select= thd->lex->current_select;
for (; sl; sl= sl->next_select())
{
Item *extracted_cond_copy;
if (!sl->cond_pushdown_is_allowed())
continue;
thd->lex->current_select= sl;
if (sl->have_window_funcs())
{
if (sl->join->group_list || sl->join->implicit_grouping)
continue;
if (!(sl->window_specs.elements == 1 &&
sl->window_specs.head()->partition_list))
continue;
extracted_cond_copy= !sl->next_select() ?
extracted_cond :
extracted_cond->build_clone(thd, thd->mem_root);
if (!extracted_cond_copy)
continue;
Item *cond_over_partition_fields;
ORDER *grouping_list= sl->window_specs.head()->partition_list->first;
sl->collect_grouping_fields(thd, grouping_list);
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
derived);
cond_over_partition_fields=
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
if (cond_over_partition_fields)
cond_over_partition_fields= cond_over_partition_fields->transform(thd,
&Item::derived_grouping_field_transformer_for_where,
(uchar*) sl);
if (cond_over_partition_fields)
{
cond_over_partition_fields->walk(
&Item::cleanup_excluding_const_fields_processor, 0, 0);
sl->cond_pushed_into_where= cond_over_partition_fields;
}
continue;
}
/*
For each select of the unit except the last one
create a clone of extracted_cond
*/
Item *extracted_cond_copy= !sl->next_select() ? extracted_cond :
extracted_cond_copy= !sl->next_select() ?
extracted_cond :
extracted_cond->build_clone(thd, thd->mem_root);
if (!extracted_cond_copy)
continue;
......@@ -1276,7 +1312,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
that could be pushed into the where clause of sl
*/
Item *cond_over_grouping_fields;
sl->collect_grouping_fields(thd);
sl->collect_grouping_fields(thd, sl->join->group_list);
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
derived);
cond_over_grouping_fields=
......
......@@ -6878,14 +6878,15 @@ void binlog_unsafe_map_init()
st_select_lex and saves this fields.
*/
void st_select_lex::collect_grouping_fields(THD *thd)
void st_select_lex::collect_grouping_fields(THD *thd,
ORDER *grouping_list)
{
grouping_tmp_fields.empty();
List_iterator<Item> li(join->fields_list);
Item *item= li++;
for (uint i= 0; i < master_unit()->derived->table->s->fields; i++, (item=li++))
{
for (ORDER *ord= join->group_list; ord; ord= ord->next)
for (ORDER *ord= grouping_list; ord; ord= ord->next)
{
if ((*ord->item)->eq((Item*)item, 0))
{
......
......@@ -1223,7 +1223,7 @@ class st_select_lex: public st_select_lex_node
With_element *find_table_def_in_with_clauses(TABLE_LIST *table);
bool check_unrestricted_recursive(bool only_standard_compliant);
bool check_subqueries_with_recursive_references();
void collect_grouping_fields(THD *thd);
void collect_grouping_fields(THD *thd, ORDER *grouping_list);
void check_cond_extraction_for_grouping_fields(Item *cond,
TABLE_LIST *derived);
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
......@@ -1248,7 +1248,7 @@ class st_select_lex: public st_select_lex_node
bool have_window_funcs() const { return (window_funcs.elements !=0); }
bool cond_pushdown_is_allowed() const
{ return !have_window_funcs() && !olap && !explicit_limit; }
{ return !olap && !explicit_limit; }
private:
bool m_non_agg_field_used;
......
......@@ -1409,6 +1409,11 @@ class JOIN :public Sql_alloc
bool set_group_rpa;
/** Exec time only: TRUE <=> current group has been sent */
bool group_sent;
/**
TRUE if the query contains an aggregate function but has no GROUP
BY clause.
*/
bool implicit_grouping;
bool is_for_splittable_grouping_derived;
bool with_two_phase_optimization;
......@@ -1701,11 +1706,6 @@ class JOIN :public Sql_alloc
*/
void optimize_distinct();
/**
TRUE if the query contains an aggregate function but has no GROUP
BY clause.
*/
bool implicit_grouping;
void cleanup_item_list(List<Item> &items) const;
bool make_aggr_tables_info();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment