new optimisation for ref_null (SCRUM) (WL#818)
This commit is contained in:
parent
d9b108c12f
commit
7e34954b5e
@ -828,8 +828,21 @@ a t1.a in (select t2.a from t2)
|
|||||||
explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
|
explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index
|
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index
|
||||||
|
2 DEPENDENT SUBQUERY t2 index_in a a 5 const 2 Using where; Using index
|
||||||
|
CREATE TABLE t3 (a int(11) default '0');
|
||||||
|
INSERT INTO t3 VALUES (1),(2),(3);
|
||||||
|
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
|
||||||
|
a t1.a in (select t2.a from t2,t3 where t3.a=t2.a)
|
||||||
|
1 1
|
||||||
|
2 1
|
||||||
|
3 1
|
||||||
|
4 0
|
||||||
|
explain SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index
|
||||||
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 const 2 Using where; Using index
|
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 const 2 Using where; Using index
|
||||||
drop table t1,t2;
|
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where
|
||||||
|
drop table t1,t2,t3;
|
||||||
create table t1 (a float);
|
create table t1 (a float);
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
|
@ -469,7 +469,11 @@ INSERT INTO t1 VALUES (1),(2),(3),(4);
|
|||||||
INSERT INTO t2 VALUES (1),(2),(3);
|
INSERT INTO t2 VALUES (1),(2),(3);
|
||||||
SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
|
SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
|
||||||
explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
|
explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
|
||||||
drop table t1,t2;
|
CREATE TABLE t3 (a int(11) default '0');
|
||||||
|
INSERT INTO t3 VALUES (1),(2),(3);
|
||||||
|
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
|
||||||
|
explain SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
|
||||||
|
drop table t1,t2,t3;
|
||||||
|
|
||||||
#LIMIT is not supported now
|
#LIMIT is not supported now
|
||||||
create table t1 (a float);
|
create table t1 (a float);
|
||||||
|
@ -669,6 +669,7 @@ public:
|
|||||||
Item_is_not_null_test(Item_in_subselect* ow, Item *a)
|
Item_is_not_null_test(Item_in_subselect* ow, Item *a)
|
||||||
:Item_func_isnull(a), owner(ow)
|
:Item_func_isnull(a), owner(ow)
|
||||||
{}
|
{}
|
||||||
|
enum Functype functype() const { return ISNOTNULLTEST_FUNC; }
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "is_not_null_test"; }
|
const char *func_name() const { return "is_not_null_test"; }
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
GE_FUNC,GT_FUNC,FT_FUNC,
|
GE_FUNC,GT_FUNC,FT_FUNC,
|
||||||
LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
|
LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
|
||||||
COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC, BETWEEN, IN_FUNC,
|
COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC, BETWEEN, IN_FUNC,
|
||||||
INTERVAL_FUNC,
|
INTERVAL_FUNC, ISNOTNULLTEST_FUNC,
|
||||||
SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC,
|
SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC,
|
||||||
SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC,
|
SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC,
|
||||||
SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
|
SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
|
||||||
|
@ -999,8 +999,15 @@ int subselect_indexin_engine::exec()
|
|||||||
DBUG_ENTER("subselect_indexin_engine::exec");
|
DBUG_ENTER("subselect_indexin_engine::exec");
|
||||||
int error;
|
int error;
|
||||||
TABLE *table= tab->table;
|
TABLE *table= tab->table;
|
||||||
|
|
||||||
((Item_in_subselect *) item)->value= 0;
|
((Item_in_subselect *) item)->value= 0;
|
||||||
if ((tab->ref.key_err= (*tab->ref.key_copy)->copy()))
|
if (check_null)
|
||||||
|
{
|
||||||
|
*tab->null_ref_key= 0;
|
||||||
|
((Item_in_subselect *) item)->was_null= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*tab->ref.key_copy) && (tab->ref.key_err= (*tab->ref.key_copy)->copy()))
|
||||||
{
|
{
|
||||||
table->status= STATUS_NOT_FOUND;
|
table->status= STATUS_NOT_FOUND;
|
||||||
error= -1;
|
error= -1;
|
||||||
@ -1022,12 +1029,21 @@ int subselect_indexin_engine::exec()
|
|||||||
{
|
{
|
||||||
if (!cond || cond->val_int())
|
if (!cond || cond->val_int())
|
||||||
{
|
{
|
||||||
|
if (check_null && *tab->null_ref_key)
|
||||||
|
((Item_in_subselect *) item)->was_null= 1;
|
||||||
|
else
|
||||||
((Item_in_subselect *) item)->value= 1;
|
((Item_in_subselect *) item)->value= 1;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (!check_null || *tab->null_ref_key)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
*tab->null_ref_key= 1;
|
||||||
|
if (safe_index_read(tab))
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
error= table->file->index_next_same(table->record[0],
|
error= table->file->index_next_same(table->record[0],
|
||||||
tab->ref.key_buff,
|
tab->ref.key_buff,
|
||||||
tab->ref.key_length);
|
tab->ref.key_length);
|
||||||
|
@ -228,6 +228,7 @@ public:
|
|||||||
friend class Item_asterisk_remover;
|
friend class Item_asterisk_remover;
|
||||||
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 subselect_indexin_engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ALL/ANY/SOME subselect */
|
/* ALL/ANY/SOME subselect */
|
||||||
@ -337,10 +338,13 @@ public:
|
|||||||
|
|
||||||
class subselect_indexin_engine: public subselect_simplein_engine
|
class subselect_indexin_engine: public subselect_simplein_engine
|
||||||
{
|
{
|
||||||
|
bool check_null;
|
||||||
public:
|
public:
|
||||||
subselect_indexin_engine(THD *thd, st_join_table *tab_arg,
|
subselect_indexin_engine(THD *thd, st_join_table *tab_arg,
|
||||||
Item_subselect *subs, Item *where)
|
Item_subselect *subs, Item *where,
|
||||||
:subselect_simplein_engine(thd, tab_arg, subs, where)
|
bool chk_null)
|
||||||
|
:subselect_simplein_engine(thd, tab_arg, subs, where),
|
||||||
|
check_null(chk_null)
|
||||||
{}
|
{}
|
||||||
int exec();
|
int exec();
|
||||||
};
|
};
|
||||||
|
@ -456,7 +456,7 @@ err:
|
|||||||
bool JOIN::test_in_subselect(Item **where)
|
bool JOIN::test_in_subselect(Item **where)
|
||||||
{
|
{
|
||||||
if (conds->type() == Item::FUNC_ITEM &&
|
if (conds->type() == Item::FUNC_ITEM &&
|
||||||
((class Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
|
((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
|
||||||
((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM &&
|
((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM &&
|
||||||
((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM)
|
((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM)
|
||||||
{
|
{
|
||||||
@ -763,10 +763,12 @@ JOIN::optimize()
|
|||||||
/*
|
/*
|
||||||
is this simple IN subquery?
|
is this simple IN subquery?
|
||||||
*/
|
*/
|
||||||
if (!group_list && !order && !having &&
|
if (!group_list && !order &&
|
||||||
unit->item && unit->item->substype() == Item_subselect::IN_SUBS &&
|
unit->item && unit->item->substype() == Item_subselect::IN_SUBS &&
|
||||||
tables == 1 && conds &&
|
tables == 1 && conds &&
|
||||||
!unit->first_select()->next_select())
|
!unit->first_select()->next_select())
|
||||||
|
{
|
||||||
|
if (!having)
|
||||||
{
|
{
|
||||||
Item *where= 0;
|
Item *where= 0;
|
||||||
if (join_tab[0].type == JT_EQ_REF)
|
if (join_tab[0].type == JT_EQ_REF)
|
||||||
@ -776,7 +778,8 @@ JOIN::optimize()
|
|||||||
join_tab[0].type= JT_SIMPLE_IN;
|
join_tab[0].type= JT_SIMPLE_IN;
|
||||||
error= 0;
|
error= 0;
|
||||||
DBUG_RETURN(unit->item->
|
DBUG_RETURN(unit->item->
|
||||||
change_engine(new subselect_simplein_engine(thd, join_tab,
|
change_engine(new subselect_simplein_engine(thd,
|
||||||
|
join_tab,
|
||||||
unit->item,
|
unit->item,
|
||||||
where)));
|
where)));
|
||||||
}
|
}
|
||||||
@ -788,13 +791,29 @@ JOIN::optimize()
|
|||||||
join_tab[0].type= JT_INDEX_IN;
|
join_tab[0].type= JT_INDEX_IN;
|
||||||
error= 0;
|
error= 0;
|
||||||
DBUG_RETURN(unit->item->
|
DBUG_RETURN(unit->item->
|
||||||
change_engine(new subselect_indexin_engine(thd, join_tab,
|
change_engine(new subselect_indexin_engine(thd,
|
||||||
|
join_tab,
|
||||||
unit->item,
|
unit->item,
|
||||||
where)));
|
where,
|
||||||
|
0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (join_tab[0].type == JT_REF_OR_NULL &&
|
||||||
|
having->type() == Item::FUNC_ITEM &&
|
||||||
|
((Item_func *) having)->functype() ==
|
||||||
|
Item_func::ISNOTNULLTEST_FUNC)
|
||||||
|
{
|
||||||
|
join_tab[0].type= JT_INDEX_IN;
|
||||||
|
error= 0;
|
||||||
|
DBUG_RETURN(unit->item->
|
||||||
|
change_engine(new subselect_indexin_engine(thd,
|
||||||
|
join_tab,
|
||||||
|
unit->item,
|
||||||
|
conds,
|
||||||
|
1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Need to tell Innobase that to play it safe, it should fetch all
|
Need to tell Innobase that to play it safe, it should fetch all
|
||||||
columns of the tables: this is because MySQL may build row
|
columns of the tables: this is because MySQL may build row
|
||||||
@ -5445,7 +5464,7 @@ int report_error(TABLE *table, int error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int safe_index_read(JOIN_TAB *tab)
|
int safe_index_read(JOIN_TAB *tab)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
TABLE *table= tab->table;
|
TABLE *table= tab->table;
|
||||||
|
@ -411,3 +411,4 @@ bool cp_buffer_from_ref(TABLE_REF *ref);
|
|||||||
bool error_if_full_join(JOIN *join);
|
bool error_if_full_join(JOIN *join);
|
||||||
void relink_tables(SELECT_LEX *select_lex);
|
void relink_tables(SELECT_LEX *select_lex);
|
||||||
int report_error(TABLE *table, int error);
|
int report_error(TABLE *table, int error);
|
||||||
|
int safe_index_read(JOIN_TAB *tab);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user