Skip to content

Commit 0dc1425

Browse files
author
Alexander Barkov
committed
MDEV-7950 Item_func::type() takes 0.26% in OLTP RO
Step #7 (mostly preparatory for the next step #8): Splitting the function get_mm_parts() into a virtual method in Item. This changes a virtual call for item->type() into a virtual call for item->get_mm_tree(), but also *removes* one virtual call Item_cond::functype(), which used to distinguish between COND_AND_FUNC vs COND_OR_FUNC.
1 parent 58d7e35 commit 0dc1425

File tree

3 files changed

+109
-95
lines changed

3 files changed

+109
-95
lines changed

sql/item.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class user_var_entry;
6262
class JOIN;
6363
struct KEY_FIELD;
6464
struct SARGABLE_PARAM;
65+
class RANGE_OPT_PARAM;
66+
class SEL_TREE;
6567

6668

6769
static inline uint32
@@ -1147,6 +1149,15 @@ class Item: public Type_std_attributes
11471149
{
11481150
return;
11491151
}
1152+
/*
1153+
Make a select tree for all keys in a condition or a condition part
1154+
@param param Context
1155+
@param cond_ptr[OUT] Store a replacement item here if the condition
1156+
can be simplified, e.g.:
1157+
WHERE part1 OR part2 OR part3
1158+
with one of the partN evalutating to SEL_TREE::ALWAYS.
1159+
*/
1160+
virtual SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
11501161
/*
11511162
Checks whether the item is:
11521163
- a simple equality (field=field_item or field=constant_item), or

sql/item_cmpfunc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,7 @@ class Item_cond :public Item_bool_func
17331733
void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
17341734
uint *and_level, table_map usable_tables,
17351735
SARGABLE_PARAM **sargables);
1736+
SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
17361737
virtual void print(String *str, enum_query_type query_type);
17371738
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
17381739
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
@@ -2082,6 +2083,7 @@ class Item_cond_and :public Item_cond
20822083
COND_EQUAL **cond_equal_ref);
20832084
void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
20842085
table_map usable_tables, SARGABLE_PARAM **sargables);
2086+
SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
20852087
};
20862088

20872089
inline bool is_cond_and(Item *item)

sql/opt_range.cc

Lines changed: 96 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,6 @@ static SEL_TREE * get_mm_parts(RANGE_OPT_PARAM *param,COND *cond_func,Field *fie
952952
static SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param,COND *cond_func,Field *field,
953953
KEY_PART *key_part,
954954
Item_func::Functype type,Item *value);
955-
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond);
956955

957956
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
958957
static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
@@ -3131,7 +3130,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
31313130

31323131
if (cond)
31333132
{
3134-
if ((tree= get_mm_tree(&param, &cond)))
3133+
if ((tree= cond->get_mm_tree(&param, &cond)))
31353134
{
31363135
if (tree->type == SEL_TREE::IMPOSSIBLE)
31373136
{
@@ -3628,7 +3627,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
36283627

36293628
thd->no_errors=1;
36303629

3631-
tree= get_mm_tree(&param, cond);
3630+
tree= cond[0]->get_mm_tree(&param, cond);
36323631

36333632
if (!tree)
36343633
goto free_alloc;
@@ -4061,7 +4060,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
40614060
SEL_TREE *tree;
40624061
int res;
40634062

4064-
tree= get_mm_tree(range_par, &pprune_cond);
4063+
tree= pprune_cond->get_mm_tree(range_par, &pprune_cond);
40654064
if (!tree)
40664065
goto all_used;
40674066

@@ -7967,104 +7966,106 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
79677966
NULL - Could not infer anything from condition cond.
79687967
SEL_TREE with type=IMPOSSIBLE - condition can never be true.
79697968
*/
7970-
7971-
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
7969+
SEL_TREE *Item_cond_and::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
79727970
{
7973-
SEL_TREE *tree=0;
7974-
SEL_TREE *ftree= 0;
7975-
Item_field *field_item= 0;
7976-
bool inv= FALSE;
7977-
Item *value= 0;
7978-
Item *cond= *cond_ptr;
7979-
DBUG_ENTER("get_mm_tree");
7980-
7981-
if (cond->type() == Item::COND_ITEM)
7971+
DBUG_ENTER("Item_cond_and::get_mm_tree");
7972+
SEL_TREE *tree= NULL;
7973+
List_iterator<Item> li(*argument_list());
7974+
Item *item;
7975+
while ((item= li++))
79827976
{
7983-
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
7977+
SEL_TREE *new_tree= li.ref()[0]->get_mm_tree(param,li.ref());
7978+
if (param->statement_should_be_aborted())
7979+
DBUG_RETURN(NULL);
7980+
tree= tree_and(param, tree, new_tree);
7981+
if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
7982+
{
7983+
/*
7984+
Do not remove 'item' from 'cond'. We return a SEL_TREE::IMPOSSIBLE
7985+
and that is sufficient for the caller to see that the whole
7986+
condition is never true.
7987+
*/
7988+
break;
7989+
}
7990+
}
7991+
DBUG_RETURN(tree);
7992+
}
79847993

7985-
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
7994+
7995+
SEL_TREE *Item_cond::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
7996+
{
7997+
DBUG_ENTER("Item_cond::get_mm_tree");
7998+
List_iterator<Item> li(*argument_list());
7999+
bool replace_cond= false;
8000+
Item *replacement_item= li++;
8001+
SEL_TREE *tree= li.ref()[0]->get_mm_tree(param, li.ref());
8002+
if (param->statement_should_be_aborted())
8003+
DBUG_RETURN(NULL);
8004+
if (tree)
8005+
{
8006+
if (tree->type == SEL_TREE::IMPOSSIBLE &&
8007+
param->remove_false_where_parts)
79868008
{
7987-
tree= NULL;
7988-
Item *item;
7989-
while ((item=li++))
7990-
{
7991-
SEL_TREE *new_tree= get_mm_tree(param,li.ref());
7992-
if (param->statement_should_be_aborted())
7993-
DBUG_RETURN(NULL);
7994-
tree= tree_and(param,tree,new_tree);
7995-
if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
7996-
{
7997-
/*
7998-
Do not remove 'item' from 'cond'. We return a SEL_TREE::IMPOSSIBLE
7999-
and that is sufficient for the caller to see that the whole
8000-
condition is never true.
8001-
*/
8002-
break;
8003-
}
8004-
}
8009+
/* See the other li.remove() call below */
8010+
li.remove();
8011+
if (argument_list()->elements <= 1)
8012+
replace_cond= true;
80058013
}
8006-
else
8007-
{ // COND OR
8008-
bool replace_cond= false;
8009-
Item *replacement_item= li++;
8010-
tree= get_mm_tree(param, li.ref());
8011-
if (param->statement_should_be_aborted())
8014+
8015+
Item *item;
8016+
while ((item= li++))
8017+
{
8018+
SEL_TREE *new_tree= li.ref()[0]->get_mm_tree(param, li.ref());
8019+
if (new_tree == NULL || param->statement_should_be_aborted())
80128020
DBUG_RETURN(NULL);
8013-
if (tree)
8021+
tree= tree_or(param, tree, new_tree);
8022+
if (tree == NULL || tree->type == SEL_TREE::ALWAYS)
80148023
{
8015-
if (tree->type == SEL_TREE::IMPOSSIBLE &&
8016-
param->remove_false_where_parts)
8017-
{
8018-
/* See the other li.remove() call below */
8019-
li.remove();
8020-
if (((Item_cond*)cond)->argument_list()->elements <= 1)
8021-
replace_cond= true;
8022-
}
8023-
8024-
Item *item;
8025-
while ((item=li++))
8026-
{
8027-
SEL_TREE *new_tree=get_mm_tree(param,li.ref());
8028-
if (new_tree == NULL || param->statement_should_be_aborted())
8029-
DBUG_RETURN(NULL);
8030-
tree= tree_or(param,tree,new_tree);
8031-
if (tree == NULL || tree->type == SEL_TREE::ALWAYS)
8032-
{
8033-
replacement_item= *li.ref();
8034-
break;
8035-
}
8024+
replacement_item= *li.ref();
8025+
break;
8026+
}
80368027

8037-
if (new_tree && new_tree->type == SEL_TREE::IMPOSSIBLE &&
8038-
param->remove_false_where_parts)
8039-
{
8040-
/*
8041-
This is a condition in form
8028+
if (new_tree && new_tree->type == SEL_TREE::IMPOSSIBLE &&
8029+
param->remove_false_where_parts)
8030+
{
8031+
/*
8032+
This is a condition in form
80428033
8043-
cond = item1 OR ... OR item_i OR ... itemN
8034+
cond = item1 OR ... OR item_i OR ... itemN
80448035
8045-
and item_i produces SEL_TREE(IMPOSSIBLE). We should remove item_i
8046-
from cond. This may cause 'cond' to become a degenerate,
8047-
one-way OR. In that case, we replace 'cond' with the remaining
8048-
item_i.
8049-
*/
8050-
li.remove();
8051-
if (((Item_cond*)cond)->argument_list()->elements <= 1)
8052-
replace_cond= true;
8053-
}
8054-
else
8055-
replacement_item= *li.ref();
8056-
}
8057-
8058-
if (replace_cond)
8059-
*cond_ptr= replacement_item;
8036+
and item_i produces SEL_TREE(IMPOSSIBLE). We should remove item_i
8037+
from cond. This may cause 'cond' to become a degenerate,
8038+
one-way OR. In that case, we replace 'cond' with the remaining
8039+
item_i.
8040+
*/
8041+
li.remove();
8042+
if (argument_list()->elements <= 1)
8043+
replace_cond= true;
80608044
}
8045+
else
8046+
replacement_item= *li.ref();
80618047
}
8062-
DBUG_RETURN(tree);
8048+
8049+
if (replace_cond)
8050+
*cond_ptr= replacement_item;
80638051
}
8052+
DBUG_RETURN(tree);
8053+
}
8054+
8055+
8056+
SEL_TREE *Item::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
8057+
{
8058+
SEL_TREE *tree=0;
8059+
SEL_TREE *ftree= 0;
8060+
Item_field *field_item= 0;
8061+
bool inv= FALSE;
8062+
Item *value= 0;
8063+
DBUG_ENTER("Item::get_mm_tree");
8064+
80648065
/* Here when simple cond */
8065-
if (cond->const_item())
8066+
if (const_item())
80668067
{
8067-
if (cond->is_expensive())
8068+
if (is_expensive())
80688069
DBUG_RETURN(0);
80698070
/*
80708071
During the cond->val_int() evaluation we can come across a subselect
@@ -8074,32 +8075,32 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
80748075
*/
80758076
MEM_ROOT *tmp_root= param->mem_root;
80768077
param->thd->mem_root= param->old_root;
8077-
tree= cond->val_int() ? new(tmp_root) SEL_TREE(SEL_TREE::ALWAYS) :
8078-
new(tmp_root) SEL_TREE(SEL_TREE::IMPOSSIBLE);
8078+
tree= val_int() ? new(tmp_root) SEL_TREE(SEL_TREE::ALWAYS) :
8079+
new(tmp_root) SEL_TREE(SEL_TREE::IMPOSSIBLE);
80798080
param->thd->mem_root= tmp_root;
80808081
DBUG_RETURN(tree);
80818082
}
80828083

80838084
table_map ref_tables= 0;
80848085
table_map param_comp= ~(param->prev_tables | param->read_tables |
80858086
param->current_table);
8086-
if (cond->type() != Item::FUNC_ITEM)
8087+
if (type() != Item::FUNC_ITEM)
80878088
{ // Should be a field
8088-
ref_tables= cond->used_tables();
8089+
ref_tables= used_tables();
80898090
if ((ref_tables & param->current_table) ||
80908091
(ref_tables & ~(param->prev_tables | param->read_tables)))
80918092
DBUG_RETURN(0);
80928093
DBUG_RETURN(new SEL_TREE(SEL_TREE::MAYBE));
80938094
}
80948095

8095-
Item_func *cond_func= (Item_func*) cond;
8096+
Item_func *cond_func= (Item_func*) this;
80968097
if (cond_func->functype() == Item_func::BETWEEN ||
80978098
cond_func->functype() == Item_func::IN_FUNC)
80988099
inv= ((Item_func_opt_neg *) cond_func)->negated;
80998100
else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
81008101
DBUG_RETURN(0);
81018102

8102-
param->cond= cond;
8103+
param->cond= this;
81038104

81048105
switch (cond_func->functype()) {
81058106
case Item_func::BETWEEN:
@@ -8149,7 +8150,7 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
81498150
}
81508151
case Item_func::MULT_EQUAL_FUNC:
81518152
{
8152-
Item_equal *item_equal= (Item_equal *) cond;
8153+
Item_equal *item_equal= (Item_equal *) this;
81538154
if (!(value= item_equal->get_const()) || value->is_expensive())
81548155
DBUG_RETURN(0);
81558156
Item_equal_fields_iterator it(*item_equal);
@@ -8160,7 +8161,7 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
81608161
Item_result cmp_type= field->cmp_type();
81618162
if (!((ref_tables | field->table->map) & param_comp))
81628163
{
8163-
tree= get_mm_parts(param, cond, field, Item_func::EQ_FUNC,
8164+
tree= get_mm_parts(param, this, field, Item_func::EQ_FUNC,
81648165
value,cmp_type);
81658166
ftree= !ftree ? tree : tree_and(param, ftree, tree);
81668167
}

0 commit comments

Comments
 (0)