mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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().
This commit is contained in:
@ -1616,10 +1616,29 @@ JOIN::optimize_inner()
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
}
|
||||
|
||||
if (setup_jtbm_semi_joins(this, join_list, &conds))
|
||||
|
||||
List<Item> eq_list;
|
||||
|
||||
if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (eq_list.elements != 0)
|
||||
{
|
||||
Item *new_cond;
|
||||
|
||||
if (eq_list.elements == 1)
|
||||
new_cond= eq_list.pop();
|
||||
else
|
||||
new_cond= new (thd->mem_root) Item_cond_and(thd, eq_list);
|
||||
|
||||
if (new_cond &&
|
||||
((new_cond->fix_fields(thd, &new_cond) ||
|
||||
!(conds= and_items(thd, conds, new_cond)) ||
|
||||
conds->fix_fields(thd, &conds))))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
eq_list.empty();
|
||||
|
||||
if (select_lex->cond_pushed_into_where)
|
||||
{
|
||||
conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
|
||||
@ -1641,6 +1660,32 @@ JOIN::optimize_inner()
|
||||
conds= optimize_cond(this, conds, join_list, FALSE,
|
||||
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
|
||||
|
||||
if (thd->lex->sql_command == SQLCOM_SELECT &&
|
||||
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
|
||||
{
|
||||
TABLE_LIST *tbl;
|
||||
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
|
||||
while ((tbl= li++))
|
||||
if (tbl->jtbm_subselect)
|
||||
{
|
||||
if (tbl->jtbm_subselect->pushdown_cond_for_in_subquery(thd, conds))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (setup_jtbm_semi_joins(this, join_list, eq_list))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (eq_list.elements != 0)
|
||||
{
|
||||
conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
|
||||
eq_list, &cond_value);
|
||||
|
||||
if (!conds &&
|
||||
cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
if (thd->lex->sql_command == SQLCOM_SELECT &&
|
||||
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
|
||||
{
|
||||
@ -1679,7 +1724,6 @@ JOIN::optimize_inner()
|
||||
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (thd->is_error())
|
||||
{
|
||||
error= 1;
|
||||
@ -13382,9 +13426,9 @@ finish:
|
||||
FALSE otherwise
|
||||
*/
|
||||
|
||||
static bool check_simple_equality(THD *thd, const Item::Context &ctx,
|
||||
Item *left_item, Item *right_item,
|
||||
COND_EQUAL *cond_equal)
|
||||
bool check_simple_equality(THD *thd, const Item::Context &ctx,
|
||||
Item *left_item, Item *right_item,
|
||||
COND_EQUAL *cond_equal)
|
||||
{
|
||||
Item *orig_left_item= left_item;
|
||||
Item *orig_right_item= right_item;
|
||||
|
Reference in New Issue
Block a user