mirror of
https://github.com/MariaDB/server.git
synced 2025-08-09 22:24:09 +03:00
MDEV-9712 Performance degradation of nested NULLIF
10.1 introduced a problem: Execution time for various recursive stages (walk, update_used_table, and propagate_equal_fields) in NULLIF is O(recursion_level^2), because complexity is doubled on every recursion level when we copy args[0] to args[2]. This change fixes to avoid unnecessary recursion in: - Item_func_nullif::walk - Item_func_nullif::update_used_tables - Item_func_nullif::propagate_equal_fields when possible.
This commit is contained in:
@@ -2507,6 +2507,23 @@ void Item_func_nullif::split_sum_func(THD *thd, Item **ref_pointer_array,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_nullif::walk(Item_processor processor,
|
||||||
|
bool walk_subquery, uchar *arg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
No needs to iterate through args[2] when it's just a copy of args[0].
|
||||||
|
See MDEV-9712 Performance degradation of nested NULLIF
|
||||||
|
*/
|
||||||
|
uint tmp_count= arg_count == 2 || args[0] == args[2] ? 2 : 3;
|
||||||
|
for (uint i= 0; i < tmp_count; i++)
|
||||||
|
{
|
||||||
|
if (args[i]->walk(processor, walk_subquery, arg))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (this->*processor)(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func_nullif::update_used_tables()
|
void Item_func_nullif::update_used_tables()
|
||||||
{
|
{
|
||||||
if (m_cache)
|
if (m_cache)
|
||||||
@@ -2517,7 +2534,14 @@ void Item_func_nullif::update_used_tables()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Item_func::update_used_tables();
|
/*
|
||||||
|
MDEV-9712 Performance degradation of nested NULLIF
|
||||||
|
No needs to iterate through args[2] when it's just a copy of args[0].
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(arg_count == 3);
|
||||||
|
used_tables_and_const_cache_init();
|
||||||
|
used_tables_and_const_cache_update_and_join(args[0] == args[2] ? 2 : 3,
|
||||||
|
args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1026,6 +1026,7 @@ public:
|
|||||||
String *str_op(String *str);
|
String *str_op(String *str);
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
|
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
|
||||||
uint decimal_precision() const { return args[2]->decimal_precision(); }
|
uint decimal_precision() const { return args[2]->decimal_precision(); }
|
||||||
const char *func_name() const { return "nullif"; }
|
const char *func_name() const { return "nullif"; }
|
||||||
void print(String *str, enum_query_type query_type);
|
void print(String *str, enum_query_type query_type);
|
||||||
@@ -1037,13 +1038,21 @@ public:
|
|||||||
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
|
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
|
||||||
{
|
{
|
||||||
Context cmpctx(ANY_SUBST, cmp.compare_type(), cmp.compare_collation());
|
Context cmpctx(ANY_SUBST, cmp.compare_type(), cmp.compare_collation());
|
||||||
|
const Item *old0= args[0];
|
||||||
args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
|
args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
|
||||||
cond, &args[0]);
|
cond, &args[0]);
|
||||||
args[1]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
|
args[1]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
|
||||||
cond, &args[1]);
|
cond, &args[1]);
|
||||||
args[2]->propagate_equal_fields_and_change_item_tree(thd,
|
/*
|
||||||
Context_identity(),
|
MDEV-9712 Performance degradation of nested NULLIF
|
||||||
cond, &args[2]);
|
ANY_SUBST is more relaxed than IDENTITY_SUBST.
|
||||||
|
If ANY_SUBST did not change args[0],
|
||||||
|
then we can skip propagation for args[2].
|
||||||
|
*/
|
||||||
|
if (old0 != args[0])
|
||||||
|
args[2]->propagate_equal_fields_and_change_item_tree(thd,
|
||||||
|
Context_identity(),
|
||||||
|
cond, &args[2]);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user