From 402e58cf788af1defe3e58cacedbdd77f5dffcf0 Mon Sep 17 00:00:00 2001 From: Sergey Petrunia Date: Sun, 14 Jun 2009 14:01:10 +0400 Subject: [PATCH] MWL#17: Table elimination - Do not show eliminated tables in the output of EXPLAIN EXTENDED --- mysql-test/r/table_elim.result | 15 +++++++++++---- mysql-test/t/table_elim.test | 3 ++- sql/sql_select.cc | 35 +++++++++++++++++++++++++++------- sql/sql_select.h | 5 ++--- sql/table.h | 3 ++- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/table_elim.result b/mysql-test/r/table_elim.result index 0c0672e890b..8ff8786a574 100644 --- a/mysql-test/r/table_elim.result +++ b/mysql-test/r/table_elim.result @@ -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; id select_type table type possible_keys key key_len ref rows Extra 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; a 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 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 # Elimination when done within an outer join nest: -explain +explain extended select t0.* from 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; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 ALL NULL NULL NULL NULL 4 -1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 4 100.00 +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 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 diff --git a/mysql-test/t/table_elim.test b/mysql-test/t/table_elim.test index 4c8c360ea04..0e4225f8c9a 100644 --- a/mysql-test/t/table_elim.test +++ b/mysql-test/t/table_elim.test @@ -17,6 +17,7 @@ create table t3 (a int primary key, b int) --echo # This will be eliminated: 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; @@ -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; --echo # Elimination when done within an outer join nest: -explain +explain extended select t0.* from t0 left join (t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7a2fb857504..6041cd6edfb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2386,6 +2386,10 @@ mysql_select(THD *thd, Item ***rref_pointer_array, } else { + // psergey{ + if (select_options & SELECT_DESCRIBE) + free_join= 0; + // }psergey if (!(join= new JOIN(thd, fields, select_options, result))) DBUG_RETURN(TRUE); 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)); tab->type= JT_CONST; - tab->eliminated= TRUE; + join->eliminated_tables |= table->map; *const_tables |= table->map; join->const_table_map|= table->map; 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; table_map used_tables; DBUG_ENTER("eliminate_tables"); + + join->eliminated_tables= 0; + + /* MWL#17 is only about outer join elimination, so: */ if (!join->outer_join) DBUG_VOID_RETURN; @@ -6060,6 +6068,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) tables= 1; const_tables= 0; const_table_map= 0; + eliminated_tables= 0; tmp_table_param.field_count= tmp_table_param.sum_func_count= tmp_table_param.func_count= 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; //psergey-todo: - if (tab->eliminated) + if (table->map & join->eliminated_tables) { used_tables|=table->map; continue; @@ -16912,6 +16921,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) */ static void print_join(THD *thd, + table_map eliminated_tables, String *str, List *tables, enum_query_type query_type) @@ -16927,12 +16937,22 @@ static void print_join(THD *thd, *t= ti++; 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; for (TABLE_LIST **tbl= table + 1; tbl < end; 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) { /* MySQL converts right to left joins */ @@ -16942,7 +16962,7 @@ static void print_join(THD *thd, str->append(STRING_WITH_LEN(" straight_join ")); else str->append(STRING_WITH_LEN(" join ")); - curr->print(thd, str, query_type); + curr->print(thd, eliminated_tables, str, query_type); if (curr->on_expr) { 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 */ -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) { 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(')'); } 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 ")); /* 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) { diff --git a/sql/sql_select.h b/sql/sql_select.h index d0c16558c91..0ca47e7ce13 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -211,9 +211,6 @@ typedef struct st_join_table { /** Bitmap of nested joins this table is part of */ nested_join_map embedding_map; - //psergey-todo: more justified place - bool eliminated; - void cleanup(); inline bool is_using_loose_index_scan() { @@ -289,6 +286,8 @@ public: */ bool resume_nested_loop; table_map const_table_map,found_const_table_map; + + table_map eliminated_tables; /* Bitmap of all inner tables from outer joins */ diff --git a/sql/table.h b/sql/table.h index cc54daccf9d..f443d591dec 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1366,7 +1366,8 @@ struct TABLE_LIST return (derived || view || schema_table || (create && !table->db_stat) || !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, TABLE_LIST *view); bool set_insert_values(MEM_ROOT *mem_root);