diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_explain.cc | 250 | ||||
-rw-r--r-- | sql/sql_explain.h | 88 | ||||
-rw-r--r-- | sql/sql_lex.cc | 8 | ||||
-rw-r--r-- | sql/sql_lex.h | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 17 |
5 files changed, 283 insertions, 83 deletions
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 7c3918bfd20..d767592bd99 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -541,7 +541,8 @@ uint Explain_union::make_union_table_name(char *buf) int Explain_union::print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, - bool is_analyze) + bool is_analyze, + bool is_eliminated) { THD *thd= output->thd; MEM_ROOT *mem_root= thd->mem_root; @@ -642,7 +643,8 @@ int Explain_union::print_explain(Explain_query *query, void Explain_union::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze, - bool no_tmp_tbl) + bool no_tmp_tbl, + bool is_eliminated) { Json_writer_nesting_guard guard(writer); char table_name_buffer[SAFE_NAME_LEN]; @@ -713,8 +715,9 @@ int Explain_node::print_explain_for_children(Explain_query *query, { for (int i= 0; i < (int) children.elements(); i++) { - Explain_node *node= query->get_node(children.at(i)); - if (node->print_explain(query, output, explain_flags, is_analyze)) + Explain_node *node= query->get_node(children.at(i).select_no); + if (node->print_explain(query, output, explain_flags, is_analyze, + children.at(i).is_eliminated)) return 1; } return 0; @@ -758,7 +761,7 @@ void Explain_node::print_explain_json_for_children(Explain_query *query, bool started= false; for (int i= 0; i < (int) children.elements(); i++) { - Explain_node *node= query->get_node(children.at(i)); + Explain_node *node= query->get_node(children.at(i).select_no); /* Derived tables are printed inside Explain_table_access objects */ if (!is_connection_printable_in_json(node->connection_type)) @@ -771,7 +774,8 @@ void Explain_node::print_explain_json_for_children(Explain_query *query, } writer->start_object(); - node->print_explain_json(query, writer, is_analyze, no_tmp_tbl); + node->print_explain_json(query, writer, is_analyze, no_tmp_tbl, + children.at(i).is_eliminated); writer->end_object(); } @@ -821,7 +825,8 @@ Explain_basic_join::~Explain_basic_join() int Explain_select::print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze) + uint8 explain_flags, bool is_analyze, + bool is_eliminated) { THD *thd= output->thd; MEM_ROOT *mem_root= thd->mem_root; @@ -885,13 +890,20 @@ int Explain_select::print_explain(Explain_query *query, } } - for (uint i=0; i< n_join_tabs; i++) + /* + If there is no elimination of the whole node then do the first pass: + print the tables which are not eliminated individually + */ + if (!is_eliminated) { - join_tabs[i]->print_explain(output, explain_flags, is_analyze, select_id, - select_type, using_tmp, using_fs); - if (i == 0) + for (uint i= 0; i < n_join_tabs; i++) { - /* + if (unlikely(join_tabs[i]->is_eliminated)) + continue; + join_tabs[i]->print_explain(output, explain_flags, is_analyze, + select_id, select_type, using_tmp, + using_fs); + /* "Using temporary; Using filesort" should only be shown near the 1st table */ @@ -899,11 +911,25 @@ int Explain_select::print_explain(Explain_query *query, using_fs= false; } } + + /* + Second pass: print the tables which have been eliminated + either due to the whole node elimination or individually + */ + for (uint i= 0; i < n_join_tabs; i++) + { + if (unlikely(join_tabs[i]->is_eliminated || is_eliminated)) + join_tabs[i]->print_explain(output, explain_flags, is_analyze, + select_id, select_type, false, + false, is_eliminated); + } + for (uint i=0; i< n_join_tabs; i++) { Explain_basic_join* nest; if ((nest= join_tabs[i]->sjm_nest)) - nest->print_explain(query, output, explain_flags, is_analyze); + nest->print_explain(query, output, explain_flags, is_analyze, + is_eliminated); } } @@ -913,7 +939,8 @@ int Explain_select::print_explain(Explain_query *query, int Explain_basic_join::print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze) + uint8 explain_flags, bool is_analyze, + bool is_eliminated) { for (uint i=0; i< n_join_tabs; i++) { @@ -952,9 +979,20 @@ void Explain_select::add_linkage(Json_writer *writer) void Explain_select::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze, - bool no_tmp_tbl) + bool no_tmp_tbl, + bool is_eliminated) { Json_writer_nesting_guard guard(writer); + if (unlikely(is_eliminated)) + { + writer->add_member("query_block").start_object(); + writer->add_member("select_id").add_ll(select_id); + writer->add_member("eliminated").add_bool(true); + Explain_basic_join::print_explain_json_interns(query, writer, is_analyze, + no_tmp_tbl, is_eliminated); + writer->end_object(); + return; + } bool started_cache= print_explain_json_cache(writer, is_analyze); @@ -1059,7 +1097,7 @@ void Explain_select::print_explain_json(Explain_query *query, } Explain_basic_join::print_explain_json_interns(query, writer, is_analyze, - no_tmp_tbl); + no_tmp_tbl, is_eliminated); for (;started_objects; started_objects--) writer->end_object(); @@ -1139,12 +1177,14 @@ void Explain_aggr_window_funcs::print_json_members(Json_writer *writer, void Explain_basic_join::print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl) + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated) { writer->add_member("query_block").start_object(); writer->add_member("select_id").add_ll(select_id); - print_explain_json_interns(query, writer, is_analyze, no_tmp_tbl); + print_explain_json_interns(query, writer, is_analyze, no_tmp_tbl, + is_eliminated); writer->end_object(); } @@ -1153,27 +1193,50 @@ void Explain_basic_join::print_explain_json(Explain_query *query, void Explain_basic_join:: print_explain_json_interns(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl) + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated) { { Json_writer_array loop(writer, "nested_loop"); - for (uint i=0; i< n_join_tabs; i++) + + /* + If there is no elimination of the whole node then do the first pass: + print the tables which are not eliminated individually + */ + if (!is_eliminated) { - if (join_tabs[i]->start_dups_weedout) + for (uint i= 0; i < n_join_tabs; i++) { - writer->start_object(); - writer->add_member("duplicates_removal"); - writer->start_array(); - } + if (unlikely(join_tabs[i]->is_eliminated)) + continue; + if (join_tabs[i]->start_dups_weedout) + { + writer->start_object(); + writer->add_member("duplicates_removal"); + writer->start_array(); + } - join_tabs[i]->print_explain_json(query, writer, is_analyze, no_tmp_tbl); + join_tabs[i]->print_explain_json(query, writer, is_analyze, + no_tmp_tbl); - if (join_tabs[i]->end_dups_weedout) - { - writer->end_array(); - writer->end_object(); + if (join_tabs[i]->end_dups_weedout) + { + writer->end_array(); + writer->end_object(); + } } } + + /* + Second pass: print the tables which have been eliminated + either due to the whole node elimination or individually + */ + for (uint i= 0; i < n_join_tabs; i++) + { + if (unlikely(join_tabs[i]->is_eliminated || is_eliminated)) + join_tabs[i]->print_explain_json(query, writer, is_analyze, + no_tmp_tbl, true); + } } // "nested_loop" print_explain_json_for_children(query, writer, is_analyze, no_tmp_tbl); } @@ -1332,8 +1395,14 @@ double Explain_table_access::get_r_filtered() int Explain_table_access::print_explain(select_result_sink *output, uint8 explain_flags, bool is_analyze, uint select_id, const char *select_type, - bool using_temporary, bool using_filesort) + bool using_temporary, bool using_filesort, + bool is_parent_node_eliminated) { + // Check whether the table is eliminated itself or its parent node + if (unlikely(is_eliminated || is_parent_node_eliminated)) + return print_explain_eliminated(output, explain_flags, is_analyze, + select_id, select_type); + THD *thd= output->thd; // note: for SHOW EXPLAIN, this is target thd. MEM_ROOT *mem_root= thd->mem_root; @@ -1552,6 +1621,72 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai } +int Explain_table_access::print_explain_eliminated(select_result_sink *output, + uint8 explain_flags, + bool is_analyze, + uint select_id, + const char *select_type) +{ + THD *thd= output->thd; // note: for SHOW EXPLAIN, this is target thd. + MEM_ROOT *mem_root= thd->mem_root; + + List<Item> item_list; + Item *item_null= new (mem_root) Item_null(thd); + + /* `id` column */ + item_list.push_back(new (mem_root) Item_int(thd, (int32) select_id), + mem_root); + + /* `select_type` column */ + push_str(thd, &item_list, select_type); + + /* `table` column */ + push_string(thd, &item_list, &table_name); + + /* `partitions` column */ + if (explain_flags & DESCRIBE_PARTITIONS) + item_list.push_back(item_null, mem_root); + + /* `type` column */ + push_str(thd, &item_list, "Eliminated"); + + /* `possible_keys` column */ + item_list.push_back(item_null, mem_root); + + /* `key` */ + item_list.push_back(item_null, mem_root); + + /* `key_len` */ + item_list.push_back(item_null, mem_root); + + /* `ref` */ + item_list.push_back(item_null, mem_root); + + /* `rows` */ + item_list.push_back(item_null, mem_root); + + /* `r_rows` */ + if (is_analyze) + item_list.push_back(item_null, mem_root); + + /* `filtered` */ + if (explain_flags &DESCRIBE_EXTENDED || is_analyze) + item_list.push_back(item_null, mem_root); + + /* `r_filtered` */ + if (is_analyze) + item_list.push_back(item_null, mem_root); + + /* `Extra` */ + push_str(thd, &item_list, ""); + + if (output->send_data(item_list)) + return 1; + + return 0; +} + + /** Adds copy of the string to the list @@ -1760,8 +1895,15 @@ void Explain_rowid_filter::print_explain_json(Explain_query *query, void Explain_table_access::print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl) + bool is_analyze, bool no_tmp_tbl, + bool is_parent_node_eliminated) { + if (unlikely(is_eliminated || is_parent_node_eliminated)) + { + print_explain_json_eliminated(query, writer); + return; + } + Json_writer_object jsobj(writer); if (pre_join_sort) @@ -2005,6 +2147,30 @@ void Explain_table_access::print_explain_json(Explain_query *query, } +void Explain_table_access::print_explain_json_eliminated(Explain_query *query, + Json_writer *writer) +{ + Json_writer_object jsobj(writer); + writer->add_member("table").start_object(); + writer->add_member("table_name").add_str(table_name); + writer->add_member("access_type").add_str("Eliminated"); + if (derived_select_number) + { + /* This is a derived table. Print its contents here */ + writer->add_member("materialized").start_object(); + Explain_node *node= query->get_node(derived_select_number); + if (node->get_type() == Explain_node::EXPLAIN_SELECT && + ((Explain_select *) node)->is_lateral) + { + writer->add_member("lateral").add_ll(1); + } + node->print_explain_json(query, writer, false, false, true); + writer->end_object(); + } + writer->end_object(); +} + + /* Elements in this array match members of enum explain_extra_tag, defined in sql_explain.h @@ -2275,8 +2441,8 @@ void Explain_quick_select::print_key_len(String *str) int Explain_delete::print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, - bool is_analyze) + uint8 explain_flags, bool is_analyze, + bool is_eliminated) { if (deleting_all_rows) { @@ -2290,7 +2456,7 @@ int Explain_delete::print_explain(Explain_query *query, else { return Explain_update::print_explain(query, output, explain_flags, - is_analyze); + is_analyze, is_eliminated); } } @@ -2298,7 +2464,8 @@ int Explain_delete::print_explain(Explain_query *query, void Explain_delete::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze, - bool no_tmp_tbl) + bool no_tmp_tbl, + bool is_eliminated) { Json_writer_nesting_guard guard(writer); @@ -2320,7 +2487,8 @@ void Explain_delete::print_explain_json(Explain_query *query, int Explain_update::print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, - bool is_analyze) + bool is_analyze, + bool is_eliminated) { StringBuffer<64> key_buf; StringBuffer<64> key_len_buf; @@ -2417,7 +2585,8 @@ int Explain_update::print_explain(Explain_query *query, void Explain_update::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze, - bool no_tmp_tbl) + bool no_tmp_tbl, + bool is_eliminated) { Json_writer_nesting_guard guard(writer); @@ -2602,7 +2771,8 @@ void Explain_update::print_explain_json(Explain_query *query, int Explain_insert::print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, - bool is_analyze) + bool is_analyze, + bool is_eliminated) { const char *select_type="INSERT"; print_explain_row(output, explain_flags, is_analyze, @@ -2625,7 +2795,7 @@ int Explain_insert::print_explain(Explain_query *query, void Explain_insert::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze, - bool no_tmp_tbl) + bool no_tmp_tbl, bool is_eliminated) { Json_writer_nesting_guard guard(writer); diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 919d51aef8b..1fe7d08c6f8 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -120,21 +120,29 @@ public: enum explain_connection_type connection_type; protected: + struct Child_info + { + int select_no; + bool is_eliminated; + }; /* A node may have children nodes. When a node's explain structure is - created, children nodes may not yet have QPFs. This is why we store ids. + created, children nodes may not yet have QPFs. This is why we store + pairs {select_no, is_eliminated}. */ - Dynamic_array<int> children; + Dynamic_array<Child_info> children; public: - void add_child(int select_no) + void add_child(int select_no, bool is_eliminated= false) { - children.append(select_no); + children.append({select_no, is_eliminated}); } virtual int print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze)=0; + uint8 explain_flags, bool is_analyze, + bool is_eliminated= false)= 0; virtual void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl)= 0; + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated= false)= 0; int print_explain_for_children(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze); @@ -172,12 +180,15 @@ public: uint select_id; int print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze); - void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); - + uint8 explain_flags, bool is_analyze, + bool is_eliminated= false) override; + void print_explain_json(Explain_query *query, Json_writer *writer, + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated= false) override; + // OLEGS: check this func and is the flag is_eliminated required void print_explain_json_interns(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated); /* A flat array of Explain structs for tables. */ Explain_table_access** join_tabs; @@ -258,10 +269,12 @@ public: */ Explain_aggr_node* aggr_tree; - int print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze); - void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); + int print_explain(Explain_query *query, select_result_sink *output, + uint8 explain_flags, bool is_analyze, + bool is_eliminated= false) override; + void print_explain_json(Explain_query *query, Json_writer *writer, + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated= false) override; Table_access_tracker *get_using_temporary_read_tracker() { @@ -346,7 +359,7 @@ extern const char *pushed_select_text; class Explain_union : public Explain_node { public: - Explain_union(MEM_ROOT *root, bool is_analyze) : + Explain_union(MEM_ROOT *root, bool is_analyze) : Explain_node(root), union_members(PSI_INSTRUMENT_MEM), is_recursive_cte(false), fake_select_lex_explain(root, is_analyze) @@ -377,10 +390,12 @@ public: { union_members.append(select_no); } - int print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze); - void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); + int print_explain(Explain_query *query, select_result_sink *output, + uint8 explain_flags, bool is_analyze, + bool is_eliminated) override; + void print_explain_json(Explain_query *query, Json_writer *writer, + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated) override; const char *fake_select_type; bool using_filesort; @@ -755,6 +770,7 @@ public: full_scan_on_null_key(false), start_dups_weedout(false), end_dups_weedout(false), + is_eliminated(false), where_cond(NULL), cache_cond(NULL), pushed_index_cond(NULL), @@ -836,6 +852,9 @@ public: bool start_dups_weedout; bool end_dups_weedout; + + /* OLEGS: comment*/ + bool is_eliminated; /* Note: lifespan of WHERE condition is less than lifespan of this object. @@ -874,9 +893,11 @@ public: int print_explain(select_result_sink *output, uint8 explain_flags, bool is_analyze, uint select_id, const char *select_type, - bool using_temporary, bool using_filesort); + bool using_temporary, bool using_filesort, + bool is_parent_node_eliminated= false); void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); + bool is_analyze, bool no_tmp_tbl, + bool is_parent_node_eliminated= false); private: void append_tag_name(String *str, enum explain_extra_tag tag); @@ -885,6 +906,11 @@ private: double get_r_filtered(); void tag_to_json(Json_writer *writer, enum explain_extra_tag tag, bool no_tmp_tbl); + int print_explain_eliminated(select_result_sink *output, uint8 explain_flags, + bool is_analyze, uint select_id, + const char *select_type); + void print_explain_json_eliminated(Explain_query *query, + Json_writer *writer); }; @@ -965,9 +991,11 @@ public: Exec_time_tracker table_tracker; virtual int print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze); + uint8 explain_flags, bool is_analyze, + bool is_eliminated= false) override; virtual void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated= false) override; }; @@ -991,9 +1019,11 @@ public: uint get_select_id() { return 1; /* always root */ } int print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze); + uint8 explain_flags, bool is_analyze, + bool is_eliminated= false) override; void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated= false) override; }; @@ -1018,9 +1048,11 @@ public: virtual uint get_select_id() { return 1; /* always root */ } virtual int print_explain(Explain_query *query, select_result_sink *output, - uint8 explain_flags, bool is_analyze); + uint8 explain_flags, bool is_analyze, + bool is_eliminated= false) override; virtual void print_explain_json(Explain_query *query, Json_writer *writer, - bool is_analyze, bool no_tmp_tbl); + bool is_analyze, bool no_tmp_tbl, + bool is_eliminated= false) override; }; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3db784ce61d..4590804437d 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -11917,7 +11917,7 @@ bool SELECT_LEX_UNIT::explainable() const EXPLAIN/ANALYZE unit, when: (1) if it's a subquery - it's not part of eliminated WHERE/ON clause. (2) if it's a CTE - it's not hanging (needed for execution) - (3) if it's a derived - it's not merged or eliminated + (3) if it's a derived - it's not merged if it's not 1/2/3 - it's some weird internal thing, ignore it */ @@ -11927,12 +11927,12 @@ bool SELECT_LEX_UNIT::explainable() const derived && derived->derived_result && !with_element->is_hanging_recursive(): // (2) derived ? - derived->is_materialized_derived() && // (3) - !is_derived_eliminated() : + derived->is_materialized_derived() : // (3) false; } -bool SELECT_LEX_UNIT::is_derived_eliminated() const + +bool SELECT_LEX_UNIT::is_eliminated() const { if (!derived) return false; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5647484e286..6f30a1a5397 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1027,6 +1027,7 @@ public: unit_common_op common_op(); bool explainable() const; + bool is_eliminated() const; void reset_distinct(); void fix_distinct(); @@ -1040,8 +1041,6 @@ public: friend class st_select_lex; -private: - bool is_derived_eliminated() const; }; typedef class st_select_lex_unit SELECT_LEX_UNIT; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3b07122e7c1..33f02d64744 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -28228,19 +28228,17 @@ int JOIN::save_explain_data_intern(Explain_query *output, JOIN_TAB *saved_join_tab= NULL; TABLE *cur_table= tab->table; - /* Don't show eliminated tables */ - if (cur_table->map & join->eliminated_tables) - { - used_tables|= cur_table->map; - continue; - } - Explain_table_access *eta= (new (output->mem_root) Explain_table_access(output->mem_root)); if (!eta) DBUG_RETURN(1); + if (cur_table->map & join->eliminated_tables) + { + eta->is_eliminated= true; + } + if (tab->bush_root_tab != prev_bush_root_tab) { if (tab->bush_root_tab) @@ -28293,7 +28291,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, tmp_unit; tmp_unit= tmp_unit->next_unit()) if (tmp_unit->explainable()) - explain->add_child(tmp_unit->first_select()->select_number); + explain->add_child(tmp_unit->first_select()->select_number, + tmp_unit->is_eliminated()); if (select_lex->is_top_level_node()) output->query_plan_ready(); @@ -28355,7 +28354,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, DBUG_ASSERT(ref == unit->item); } - if (unit->explainable()) + if (unit->explainable() && !unit->is_eliminated()) { if (mysql_explain_union(thd, unit, result)) DBUG_VOID_RETURN; |