Commit d3ff1333 authored by Galina Shalygina's avatar Galina Shalygina

MDEV-12387 Push conditions into materialized subqueries

The logic and the implementation scheme are similar with the
MDEV-9197 Pushdown conditions into non-mergeable views/derived tables

How the push down is made on the example:

select * from t1
where a>3 and b>10 and
 (a,b) in (select x,max(y) from t2 group by x);

-->

select * from t1
where a>3 and b>10 and
  (a,b) in (select x,max(y)
            from t2
            where x>3
            group by x
            having max(y)>10);

The implementation scheme:

1. Search for the condition cond that depends only on the fields
   from the left part of the IN subquery (left_part)
2. Find fields F_group in the select of the right part of the
   IN subquery (right_part) that are used in the GROUP BY
3. Extract from the cond condition cond_where that depends only on the
   fields from the left_part that stay at the same places in the left_part
   (have the same indexes) as the F_group fields in the projection of the
   right_part
4. Transform cond_where so it can be pushed into the WHERE clause of the
   right_part and delete cond_where from the cond
5. Transform cond so it can be pushed into the HAVING clause of the right_part

The optimization is made in the
Item_in_subselect::pushdown_cond_for_in_subquery() and is controlled by the
variable condition_pushdown_for_subquery.

New test file in_subq_cond_pushdown.test is created.

There are also some changes made for setup_jtbm_semi_joins().
Now it is decomposed into the 2 procedures: setup_degenerate_jtbm_semi_joins()
that is called before optimize_cond() for cond and setup_jtbm_semi_joins()
that is called after optimize_cond().
New setup_jtbm_semi_joins() is made in the way so that the result of its work is
the same as if it was called before optimize_cond().

The code that is common for pushdown into materialized derived and into materialized
IN subqueries is factored out into pushdown_cond_for_derived(),
Item_in_subselect::pushdown_cond_for_in_subquery() and
st_select_lex::pushdown_cond_into_where_clause().
parent 569e3ad1
...@@ -632,7 +632,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -632,7 +632,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 system NULL NULL NULL NULL 1 100.00 2 DERIVED t1 system NULL NULL NULL NULL 1 100.00
Warnings: Warnings:
Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1
Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `test`.`t2`.`f3` = 6 and `<subquery4>`.`f3` = 9 Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `<subquery4>`.`f3` = 9 and `test`.`t2`.`f3` = 6
DROP TABLE t2,t1; DROP TABLE t2,t1;
# #
# MDEV-9462: Out of memory using explain on 2 empty tables # MDEV-9462: Out of memory using explain on 2 empty tables
......
This diff is collapsed.
This diff is collapsed.
...@@ -665,7 +665,8 @@ The following options may be given as the first argument: ...@@ -665,7 +665,8 @@ The following options may be given as the first argument:
join_cache_hashed, join_cache_bka, join_cache_hashed, join_cache_bka,
optimize_join_buffer_size, table_elimination, optimize_join_buffer_size, table_elimination,
extended_keys, exists_to_in, orderby_uses_equalities, extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized condition_pushdown_for_derived, split_materialized,
condition_pushdown_for_subquery
--optimizer-use-condition-selectivity=# --optimizer-use-condition-selectivity=#
Controls selectivity of which conditions the optimizer Controls selectivity of which conditions the optimizer
takes into account to calculate cardinality of a partial takes into account to calculate cardinality of a partial
...@@ -1514,7 +1515,7 @@ old-style-user-limits FALSE ...@@ -1514,7 +1515,7 @@ old-style-user-limits FALSE
optimizer-prune-level 1 optimizer-prune-level 1
optimizer-search-depth 62 optimizer-search-depth 62
optimizer-selectivity-sampling-limit 100 optimizer-selectivity-sampling-limit 100
optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
optimizer-use-condition-selectivity 1 optimizer-use-condition-selectivity 1
performance-schema FALSE performance-schema FALSE
performance-schema-accounts-size -1 performance-schema-accounts-size -1
......
...@@ -1925,7 +1925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -1925,7 +1925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
Warnings: Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7) Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
SELECT * FROM t1 SELECT * FROM t1
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
a b a b
......
...@@ -1963,7 +1963,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -1963,7 +1963,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
Warnings: Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7) Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
SELECT * FROM t1 SELECT * FROM t1
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
a b a b
......
...@@ -2673,17 +2673,17 @@ ENUM_VALUE_LIST NULL ...@@ -2673,17 +2673,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH VARIABLE_NAME OPTIMIZER_SWITCH
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
VARIABLE_SCOPE SESSION VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
......
...@@ -2883,17 +2883,17 @@ ENUM_VALUE_LIST NULL ...@@ -2883,17 +2883,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH VARIABLE_NAME OPTIMIZER_SWITCH
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
VARIABLE_SCOPE SESSION VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
......
This diff is collapsed.
...@@ -569,6 +569,7 @@ typedef bool (Item::*Item_processor) (void *arg); ...@@ -569,6 +569,7 @@ typedef bool (Item::*Item_processor) (void *arg);
typedef bool (Item::*Item_analyzer) (uchar **argp); typedef bool (Item::*Item_analyzer) (uchar **argp);
typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg); typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg); typedef void (*Cond_traverser) (const Item *item, void *arg);
typedef bool (Item::*Pushdown_checker) (uchar *arg);
struct st_cond_statistic; struct st_cond_statistic;
...@@ -601,6 +602,7 @@ class String_copier_for_item: public String_copier ...@@ -601,6 +602,7 @@ class String_copier_for_item: public String_copier
String_copier_for_item(THD *thd): m_thd(thd) { } String_copier_for_item(THD *thd): m_thd(thd) { }
}; };
class Item: public Value_source, class Item: public Value_source,
public Type_all_attributes public Type_all_attributes
{ {
...@@ -1647,7 +1649,15 @@ class Item: public Value_source, ...@@ -1647,7 +1649,15 @@ class Item: public Value_source,
or can be converted to such an exression using equalities. or can be converted to such an exression using equalities.
Not to be used for AND/OR formulas. Not to be used for AND/OR formulas.
*/ */
virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) { return false; } virtual bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return false; }
/*
TRUE if the expression depends only on fields from the left part of
IN subquery or can be converted to such an expression using equalities.
Not to be used for AND/OR formulas.
*/
virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return false; }
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; } virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
virtual bool find_function_processor (void *arg) { return 0; } virtual bool find_function_processor (void *arg) { return 0; }
...@@ -1825,8 +1835,12 @@ class Item: public Value_source, ...@@ -1825,8 +1835,12 @@ class Item: public Value_source,
{ return this; } { return this; }
virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg) virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ return this; } { return this; }
virtual Item *derived_grouping_field_transformer_for_where(THD *thd, virtual Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
uchar *arg) { return this; }
/* Now is not used. */
virtual Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{ return this; }
virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ return this; } { return this; }
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg) virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
{ return this; } { return this; }
...@@ -2023,6 +2037,33 @@ class Item: public Value_source, ...@@ -2023,6 +2037,33 @@ class Item: public Value_source,
{ {
marker &= ~EXTRACTION_MASK; marker &= ~EXTRACTION_MASK;
} }
void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg);
bool pushable_cond_checker_for_derived(uchar *arg)
{
return excl_dep_on_table(*((table_map *)arg));
}
bool pushable_cond_checker_for_subquery(uchar *arg)
{
return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
}
Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred);
Item *build_pushable_cond(THD *thd,
Pushdown_checker checker,
uchar *arg);
/*
Checks if this item depends only on the arg table
*/
bool pushable_equality_checker_for_derived(uchar *arg)
{
return (used_tables() == *((table_map *)arg));
}
/*
Checks if this item consists in the left part of arg IN subquery predicate
*/
bool pushable_equality_checker_for_subquery(uchar *arg)
{
return get_corresponding_field_in_insubq((Item_in_subselect *)arg);
}
}; };
MEM_ROOT *get_thd_memroot(THD *thd); MEM_ROOT *get_thd_memroot(THD *thd);
...@@ -2151,6 +2192,17 @@ class Item_args ...@@ -2151,6 +2192,17 @@ class Item_args
} }
return true; return true;
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
for (uint i= 0; i < arg_count; i++)
{
if (args[i]->const_item())
continue;
if (!args[i]->excl_dep_on_in_subq_left_part(subq_pred))
return false;
}
return true;
}
public: public:
Item_args(void) Item_args(void)
:args(NULL), arg_count(0) :args(NULL), arg_count(0)
...@@ -3046,10 +3098,13 @@ class Item_field :public Item_ident, ...@@ -3046,10 +3098,13 @@ class Item_field :public Item_ident,
virtual Item *update_value_transformer(THD *thd, uchar *select_arg); virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg); Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
bool excl_dep_on_table(table_map tab_map); bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel); bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
bool cleanup_excluding_fields_processor(void *arg) bool cleanup_excluding_fields_processor(void *arg)
{ return field ? 0 : cleanup_processor(arg); } { return field ? 0 : cleanup_processor(arg); }
bool cleanup_excluding_const_fields_processor(void *arg) bool cleanup_excluding_const_fields_processor(void *arg)
...@@ -4874,6 +4929,8 @@ class Item_ref :public Item_ident ...@@ -4874,6 +4929,8 @@ class Item_ref :public Item_ident
} }
bool excl_dep_on_grouping_fields(st_select_lex *sel) bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return (*ref)->excl_dep_on_grouping_fields(sel); } { return (*ref)->excl_dep_on_grouping_fields(sel); }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); }
bool cleanup_excluding_fields_processor(void *arg) bool cleanup_excluding_fields_processor(void *arg)
{ {
Item *item= real_item(); Item *item= real_item();
...@@ -5188,10 +5245,12 @@ class Item_direct_view_ref :public Item_direct_ref ...@@ -5188,10 +5245,12 @@ class Item_direct_view_ref :public Item_direct_ref
} }
bool excl_dep_on_table(table_map tab_map); bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel); bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
Item *derived_grouping_field_transformer_for_where(THD *thd, Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
uchar *arg); Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
void save_val(Field *to) void save_val(Field *to)
{ {
...@@ -6110,7 +6169,11 @@ class Item_cache: public Item_basic_constant, ...@@ -6110,7 +6169,11 @@ class Item_cache: public Item_basic_constant,
{ return convert_to_basic_const_item(thd); } { return convert_to_basic_const_item(thd); }
Item *derived_field_transformer_for_where(THD *thd, uchar *arg) Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); } { return convert_to_basic_const_item(thd); }
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); }
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); }
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); } { return convert_to_basic_const_item(thd); }
}; };
......
...@@ -1272,7 +1272,11 @@ class Item_func_nullif :public Item_func_case_expression ...@@ -1272,7 +1272,11 @@ class Item_func_nullif :public Item_func_case_expression
{ reset_first_arg_if_needed(); return this; } { reset_first_arg_if_needed(); return this; }
Item *derived_field_transformer_for_where(THD *thd, uchar *arg) Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; } { reset_first_arg_if_needed(); return this; }
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; }
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; }
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; } { reset_first_arg_if_needed(); return this; }
}; };
...@@ -3135,6 +3139,8 @@ class Item_equal: public Item_bool_func ...@@ -3135,6 +3139,8 @@ class Item_equal: public Item_bool_func
{ {
return used_tables() & tab_map; return used_tables() & tab_map;
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
friend class Item_equal_fields_iterator; friend class Item_equal_fields_iterator;
bool count_sargable_conds(void *arg); bool count_sargable_conds(void *arg);
friend class Item_equal_iterator<List_iterator_fast,Item>; friend class Item_equal_iterator<List_iterator_fast,Item>;
......
...@@ -326,6 +326,11 @@ class Item_func :public Item_func_or_sum ...@@ -326,6 +326,11 @@ class Item_func :public Item_func_or_sum
return Item_args::excl_dep_on_grouping_fields(sel); return Item_args::excl_dep_on_grouping_fields(sel);
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
}
/* /*
We assume the result of any function that has a TIMESTAMP argument to be We assume the result of any function that has a TIMESTAMP argument to be
timezone-dependent, since a TIMESTAMP value in both numeric and string timezone-dependent, since a TIMESTAMP value in both numeric and string
......
...@@ -134,6 +134,11 @@ class Item_row: public Item, ...@@ -134,6 +134,11 @@ class Item_row: public Item,
return Item_args::excl_dep_on_grouping_fields(sel); return Item_args::excl_dep_on_grouping_fields(sel);
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
}
bool check_vcol_func_processor(void *arg) {return FALSE; } bool check_vcol_func_processor(void *arg) {return FALSE; }
Item *get_copy(THD *thd) Item *get_copy(THD *thd)
{ return get_item_copy<Item_row>(thd, this); } { return get_item_copy<Item_row>(thd, this); }
......
...@@ -33,6 +33,7 @@ class subselect_hash_sj_engine; ...@@ -33,6 +33,7 @@ class subselect_hash_sj_engine;
class Item_bool_func2; class Item_bool_func2;
class Comp_creator; class Comp_creator;
class With_element; class With_element;
class Field_pair;
typedef class st_select_lex SELECT_LEX; typedef class st_select_lex SELECT_LEX;
...@@ -570,6 +571,8 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -570,6 +571,8 @@ class Item_in_subselect :public Item_exists_subselect
*/ */
bool is_registered_semijoin; bool is_registered_semijoin;
List<Field_pair> corresponding_fields;
/* /*
Used to determine how this subselect item is represented in the item tree, Used to determine how this subselect item is represented in the item tree,
in case there is a need to locate it there and replace with something else. in case there is a need to locate it there and replace with something else.
...@@ -741,6 +744,8 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -741,6 +744,8 @@ class Item_in_subselect :public Item_exists_subselect
return 0; return 0;
}; };
bool pushdown_cond_for_in_subquery(THD *thd, Item *cond);
friend class Item_ref_null_helper; friend class Item_ref_null_helper;
friend class Item_is_not_null_test; friend class Item_is_not_null_test;
friend class Item_in_optimizer; friend class Item_in_optimizer;
...@@ -852,7 +857,6 @@ class subselect_engine: public Sql_alloc, ...@@ -852,7 +857,6 @@ class subselect_engine: public Sql_alloc,
void set_row(List<Item> &item_list, Item_cache **row); void set_row(List<Item> &item_list, Item_cache **row);
}; };
class subselect_single_select_engine: public subselect_engine class subselect_single_select_engine: public subselect_engine
{ {
bool prepared; /* simple subselect is prepared */ bool prepared; /* simple subselect is prepared */
...@@ -886,9 +890,10 @@ class subselect_single_select_engine: public subselect_engine ...@@ -886,9 +890,10 @@ class subselect_single_select_engine: public subselect_engine
friend class subselect_hash_sj_engine; friend class subselect_hash_sj_engine;
friend class Item_in_subselect; friend class Item_in_subselect;
friend bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, friend bool execute_degenerate_jtbm_semi_join(THD *thd,
Item **join_where); TABLE_LIST *tbl,
Item_in_subselect *subq_pred,
List<Item> &eq_list);
}; };
......
This diff is collapsed.
...@@ -26,8 +26,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join); ...@@ -26,8 +26,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join);
bool convert_join_subqueries_to_semijoins(JOIN *join); bool convert_join_subqueries_to_semijoins(JOIN *join);
int pull_out_semijoin_tables(JOIN *join); int pull_out_semijoin_tables(JOIN *join);
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map); bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
Item **join_where); COND_EQUAL **cond_eq,
List<Item> &new_conds,
Item::cond_result *cond_value);
bool setup_degenerate_jtbm_semi_joins(JOIN *join,
List<TABLE_LIST> *join_list,
List<Item> &eq_list);
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
List<Item> &eq_list);
void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list); void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list);
// used by Loose_scan_opt // used by Loose_scan_opt
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -228,6 +228,7 @@ ...@@ -228,6 +228,7 @@
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29) #define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30) #define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31) #define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
...@@ -254,7 +255,8 @@ ...@@ -254,7 +255,8 @@
OPTIMIZER_SWITCH_EXISTS_TO_IN | \ OPTIMIZER_SWITCH_EXISTS_TO_IN | \
OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \ OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \ OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED) OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)
/* /*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
......
This diff is collapsed.
This diff is collapsed.
...@@ -2472,6 +2472,7 @@ export const char *optimizer_switch_names[]= ...@@ -2472,6 +2472,7 @@ export const char *optimizer_switch_names[]=
"orderby_uses_equalities", "orderby_uses_equalities",
"condition_pushdown_for_derived", "condition_pushdown_for_derived",
"split_materialized", "split_materialized",
"condition_pushdown_for_subquery",
"default", "default",
NullS NullS
}; };
......
This diff is collapsed.
This diff is collapsed.
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