mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
MWL#17: Table elimination
- Do not show eliminated tables in the output of EXPLAIN EXTENDED
This commit is contained in:
parent
fd485ad988
commit
402e58cf78
5 changed files with 45 additions and 16 deletions
|
@ -10,6 +10,11 @@ as select a, a as b from t1 where a in (1,3);
|
||||||
explain select t1.a from t1 left join t2 on t2.a=t1.a;
|
explain select t1.a from t1 left join t2 on t2.a=t1.a;
|
||||||
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 SIMPLE t1 ALL NULL NULL NULL NULL 4
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 4
|
||||||
|
explain extended select t1.a from t1 left join t2 on t2.a=t1.a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
|
||||||
select t1.a from t1 left join t2 on t2.a=t1.a;
|
select t1.a from t1 left join t2 on t2.a=t1.a;
|
||||||
a
|
a
|
||||||
0
|
0
|
||||||
|
@ -45,14 +50,16 @@ explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and
|
||||||
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 SIMPLE t1 ALL NULL NULL NULL NULL 4
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 4
|
||||||
# Elimination when done within an outer join nest:
|
# Elimination when done within an outer join nest:
|
||||||
explain
|
explain extended
|
||||||
select t0.*
|
select t0.*
|
||||||
from
|
from
|
||||||
t0 left join (t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and
|
t0 left join (t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and
|
||||||
t3.a=t1.a) on t0.a=t1.a;
|
t3.a=t1.a) on t0.a=t1.a;
|
||||||
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 filtered Extra
|
||||||
1 SIMPLE t0 ALL NULL NULL NULL NULL 4
|
1 SIMPLE t0 ALL NULL NULL NULL NULL 4 100.00
|
||||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t0` left join (`test`.`t1`) on((`test`.`t0`.`a` = `test`.`t1`.`a`)) where 1
|
||||||
# Elimination with aggregate functions
|
# Elimination with aggregate functions
|
||||||
explain select count(*) from t1 left join t2 on t2.a=t1.a;
|
explain select count(*) from t1 left join t2 on t2.a=t1.a;
|
||||||
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
|
||||||
|
|
|
@ -17,6 +17,7 @@ create table t3 (a int primary key, b int)
|
||||||
|
|
||||||
--echo # This will be eliminated:
|
--echo # This will be eliminated:
|
||||||
explain select t1.a from t1 left join t2 on t2.a=t1.a;
|
explain select t1.a from t1 left join t2 on t2.a=t1.a;
|
||||||
|
explain extended select t1.a from t1 left join t2 on t2.a=t1.a;
|
||||||
|
|
||||||
select t1.a from t1 left join t2 on t2.a=t1.a;
|
select t1.a from t1 left join t2 on t2.a=t1.a;
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ explain select t1.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a;
|
||||||
explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a;
|
explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a;
|
||||||
|
|
||||||
--echo # Elimination when done within an outer join nest:
|
--echo # Elimination when done within an outer join nest:
|
||||||
explain
|
explain extended
|
||||||
select t0.*
|
select t0.*
|
||||||
from
|
from
|
||||||
t0 left join (t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and
|
t0 left join (t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and
|
||||||
|
|
|
@ -2386,6 +2386,10 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// psergey{
|
||||||
|
if (select_options & SELECT_DESCRIBE)
|
||||||
|
free_join= 0;
|
||||||
|
// }psergey
|
||||||
if (!(join= new JOIN(thd, fields, select_options, result)))
|
if (!(join= new JOIN(thd, fields, select_options, result)))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
thd_proc_info(thd, "init");
|
thd_proc_info(thd, "init");
|
||||||
|
@ -2523,7 +2527,7 @@ static void mark_table_as_eliminated(JOIN *join, TABLE *table, uint *const_tbl_c
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Eliminated table %s", table->alias));
|
DBUG_PRINT("info", ("Eliminated table %s", table->alias));
|
||||||
tab->type= JT_CONST;
|
tab->type= JT_CONST;
|
||||||
tab->eliminated= TRUE;
|
join->eliminated_tables |= table->map;
|
||||||
*const_tables |= table->map;
|
*const_tables |= table->map;
|
||||||
join->const_table_map|= table->map;
|
join->const_table_map|= table->map;
|
||||||
set_position(join, (*const_tbl_count)++, tab, (KEYUSE*)0);
|
set_position(join, (*const_tbl_count)++, tab, (KEYUSE*)0);
|
||||||
|
@ -2726,6 +2730,10 @@ static void eliminate_tables(JOIN *join, uint *const_tbl_count, table_map *const
|
||||||
Item *item;
|
Item *item;
|
||||||
table_map used_tables;
|
table_map used_tables;
|
||||||
DBUG_ENTER("eliminate_tables");
|
DBUG_ENTER("eliminate_tables");
|
||||||
|
|
||||||
|
join->eliminated_tables= 0;
|
||||||
|
|
||||||
|
/* MWL#17 is only about outer join elimination, so: */
|
||||||
if (!join->outer_join)
|
if (!join->outer_join)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
|
@ -6060,6 +6068,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
|
||||||
tables= 1;
|
tables= 1;
|
||||||
const_tables= 0;
|
const_tables= 0;
|
||||||
const_table_map= 0;
|
const_table_map= 0;
|
||||||
|
eliminated_tables= 0;
|
||||||
tmp_table_param.field_count= tmp_table_param.sum_func_count=
|
tmp_table_param.field_count= tmp_table_param.sum_func_count=
|
||||||
tmp_table_param.func_count= 0;
|
tmp_table_param.func_count= 0;
|
||||||
tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
|
tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
|
||||||
|
@ -16509,7 +16518,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||||
quick_type= -1;
|
quick_type= -1;
|
||||||
|
|
||||||
//psergey-todo:
|
//psergey-todo:
|
||||||
if (tab->eliminated)
|
if (table->map & join->eliminated_tables)
|
||||||
{
|
{
|
||||||
used_tables|=table->map;
|
used_tables|=table->map;
|
||||||
continue;
|
continue;
|
||||||
|
@ -16912,6 +16921,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void print_join(THD *thd,
|
static void print_join(THD *thd,
|
||||||
|
table_map eliminated_tables,
|
||||||
String *str,
|
String *str,
|
||||||
List<TABLE_LIST> *tables,
|
List<TABLE_LIST> *tables,
|
||||||
enum_query_type query_type)
|
enum_query_type query_type)
|
||||||
|
@ -16927,12 +16937,22 @@ static void print_join(THD *thd,
|
||||||
*t= ti++;
|
*t= ti++;
|
||||||
|
|
||||||
DBUG_ASSERT(tables->elements >= 1);
|
DBUG_ASSERT(tables->elements >= 1);
|
||||||
(*table)->print(thd, str, query_type);
|
//pserey:TODO check!
|
||||||
|
(*table)->print(thd, eliminated_tables, str, query_type);
|
||||||
|
|
||||||
TABLE_LIST **end= table + tables->elements;
|
TABLE_LIST **end= table + tables->elements;
|
||||||
for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
|
for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
|
||||||
{
|
{
|
||||||
TABLE_LIST *curr= *tbl;
|
TABLE_LIST *curr= *tbl;
|
||||||
|
// psergey-todo-todo:
|
||||||
|
// base table: check
|
||||||
|
if (curr->table && (curr->table->map & eliminated_tables) ||
|
||||||
|
curr->nested_join && !(curr->nested_join->used_tables &
|
||||||
|
~eliminated_tables))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (curr->outer_join)
|
if (curr->outer_join)
|
||||||
{
|
{
|
||||||
/* MySQL converts right to left joins */
|
/* MySQL converts right to left joins */
|
||||||
|
@ -16942,7 +16962,7 @@ static void print_join(THD *thd,
|
||||||
str->append(STRING_WITH_LEN(" straight_join "));
|
str->append(STRING_WITH_LEN(" straight_join "));
|
||||||
else
|
else
|
||||||
str->append(STRING_WITH_LEN(" join "));
|
str->append(STRING_WITH_LEN(" join "));
|
||||||
curr->print(thd, str, query_type);
|
curr->print(thd, eliminated_tables, str, query_type);
|
||||||
if (curr->on_expr)
|
if (curr->on_expr)
|
||||||
{
|
{
|
||||||
str->append(STRING_WITH_LEN(" on("));
|
str->append(STRING_WITH_LEN(" on("));
|
||||||
|
@ -16996,12 +17016,13 @@ Index_hint::print(THD *thd, String *str)
|
||||||
@param str string where table should be printed
|
@param str string where table should be printed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void TABLE_LIST::print(THD *thd, String *str, enum_query_type query_type)
|
void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
|
||||||
|
enum_query_type query_type)
|
||||||
{
|
{
|
||||||
if (nested_join)
|
if (nested_join)
|
||||||
{
|
{
|
||||||
str->append('(');
|
str->append('(');
|
||||||
print_join(thd, str, &nested_join->join_list, query_type);
|
print_join(thd, eliminated_tables, str, &nested_join->join_list, query_type);
|
||||||
str->append(')');
|
str->append(')');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -17143,7 +17164,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||||
{
|
{
|
||||||
str->append(STRING_WITH_LEN(" from "));
|
str->append(STRING_WITH_LEN(" from "));
|
||||||
/* go through join tree */
|
/* go through join tree */
|
||||||
print_join(thd, str, &top_join_list, query_type);
|
print_join(thd, join->eliminated_tables, str, &top_join_list, query_type);
|
||||||
}
|
}
|
||||||
else if (where)
|
else if (where)
|
||||||
{
|
{
|
||||||
|
|
|
@ -211,9 +211,6 @@ typedef struct st_join_table {
|
||||||
/** Bitmap of nested joins this table is part of */
|
/** Bitmap of nested joins this table is part of */
|
||||||
nested_join_map embedding_map;
|
nested_join_map embedding_map;
|
||||||
|
|
||||||
//psergey-todo: more justified place
|
|
||||||
bool eliminated;
|
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
inline bool is_using_loose_index_scan()
|
inline bool is_using_loose_index_scan()
|
||||||
{
|
{
|
||||||
|
@ -289,6 +286,8 @@ public:
|
||||||
*/
|
*/
|
||||||
bool resume_nested_loop;
|
bool resume_nested_loop;
|
||||||
table_map const_table_map,found_const_table_map;
|
table_map const_table_map,found_const_table_map;
|
||||||
|
|
||||||
|
table_map eliminated_tables;
|
||||||
/*
|
/*
|
||||||
Bitmap of all inner tables from outer joins
|
Bitmap of all inner tables from outer joins
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1366,7 +1366,8 @@ struct TABLE_LIST
|
||||||
return (derived || view || schema_table || (create && !table->db_stat) ||
|
return (derived || view || schema_table || (create && !table->db_stat) ||
|
||||||
!table);
|
!table);
|
||||||
}
|
}
|
||||||
void print(THD *thd, String *str, enum_query_type query_type);
|
void print(THD *thd, table_map eliminated_tables, String *str,
|
||||||
|
enum_query_type query_type);
|
||||||
bool check_single_table(TABLE_LIST **table, table_map map,
|
bool check_single_table(TABLE_LIST **table, table_map map,
|
||||||
TABLE_LIST *view);
|
TABLE_LIST *view);
|
||||||
bool set_insert_values(MEM_ROOT *mem_root);
|
bool set_insert_values(MEM_ROOT *mem_root);
|
||||||
|
|
Loading…
Add table
Reference in a new issue