summaryrefslogtreecommitdiff
path: root/sql/sql_explain.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_explain.cc')
-rw-r--r--sql/sql_explain.cc250
1 files changed, 210 insertions, 40 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);