Commit 2ac3b39e authored by Sergei Petrunia's avatar Sergei Petrunia

EXPLAIN FORMAT=JSON: support derived tables

parent 3a5e080d
...@@ -393,4 +393,75 @@ EXPLAIN ...@@ -393,4 +393,75 @@ EXPLAIN
} }
} }
} }
#
# A derived table
#
create table t1 (a int, b int);
insert into t1 select a,a from t0;
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl
where cnt>0;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
"rows": 10,
"filtered": 100,
"attached_condition": "(tbl.cnt > 0)",
"materialized": {
"query_block": {
"select_id": 2,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
}
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl1, t1 as
tbl2 where cnt=tbl2.a;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "tbl2",
"access_type": "ALL",
"rows": 10,
"filtered": 100,
"attached_condition": "(tbl2.a is not null)"
},
"table": {
"table_name": "<derived2>",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
"key_length": "8",
"used_key_parts": ["cnt"],
"ref": ["test.tbl2.a"],
"rows": 2,
"filtered": 100,
"attached_condition": "(tbl1.cnt = tbl2.a)",
"materialized": {
"query_block": {
"select_id": 2,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
}
drop table t0; drop table t0;
...@@ -80,5 +80,18 @@ explain format=json delete from t0 where a < 3; ...@@ -80,5 +80,18 @@ explain format=json delete from t0 where a < 3;
explain format=json update t0 set a=3 where a in (2,3,4); explain format=json update t0 set a=3 where a in (2,3,4);
--echo #
--echo # A derived table
--echo #
create table t1 (a int, b int);
insert into t1 select a,a from t0;
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl
where cnt>0;
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl1, t1 as
tbl2 where cnt=tbl2.a;
drop table t0; drop table t0;
...@@ -558,18 +558,29 @@ void Explain_node::print_explain_json_for_children(Explain_query *query, ...@@ -558,18 +558,29 @@ void Explain_node::print_explain_json_for_children(Explain_query *query,
Json_writer *writer, Json_writer *writer,
bool is_analyze) bool is_analyze)
{ {
if (!children.elements()) Json_writer_nesting_guard guard(writer);
return;
bool started= false;
writer->add_member("subqueries").start_array();
for (int i= 0; i < (int) children.elements(); i++) for (int i= 0; i < (int) children.elements(); i++)
{ {
writer->start_object();
Explain_node *node= query->get_node(children.at(i)); Explain_node *node= query->get_node(children.at(i));
/* Derived tables are printed inside Explain_table_access objects */
if (node->is_derived_table)
continue;
if (!started)
{
writer->add_member("subqueries").start_array();
started= true;
}
writer->start_object();
node->print_explain_json(query, writer, is_analyze); node->print_explain_json(query, writer, is_analyze);
writer->end_object(); writer->end_object();
} }
writer->end_array();
if (started)
writer->end_array();
} }
...@@ -665,7 +676,7 @@ void Explain_select::print_explain_json(Explain_query *query, ...@@ -665,7 +676,7 @@ void Explain_select::print_explain_json(Explain_query *query,
for (uint i=0; i< n_join_tabs; i++) for (uint i=0; i< n_join_tabs; i++)
{ {
// psergey-todo: Need to honor SJM nests... // psergey-todo: Need to honor SJM nests...
join_tabs[i]->print_explain_json(writer, is_analyze); join_tabs[i]->print_explain_json(query, writer, is_analyze);
} }
} }
...@@ -1054,7 +1065,8 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -1054,7 +1065,8 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
} }
void Explain_table_access::print_explain_json(Json_writer *writer, void Explain_table_access::print_explain_json(Explain_query *query,
Json_writer *writer,
bool is_analyze) bool is_analyze)
{ {
Json_writer_nesting_guard guard(writer); Json_writer_nesting_guard guard(writer);
...@@ -1169,6 +1181,15 @@ void Explain_table_access::print_explain_json(Json_writer *writer, ...@@ -1169,6 +1181,15 @@ void Explain_table_access::print_explain_json(Json_writer *writer,
} }
} }
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);
node->print_explain_json(query, writer, is_analyze);
writer->end_object();
}
writer->end_object(); writer->end_object();
} }
......
...@@ -92,9 +92,16 @@ class Explain_node : public Sql_alloc ...@@ -92,9 +92,16 @@ class Explain_node : public Sql_alloc
EXPLAIN_INSERT EXPLAIN_INSERT
}; };
Explain_node() : is_derived_table(false) {}
virtual enum explain_node_type get_type()= 0; virtual enum explain_node_type get_type()= 0;
virtual int get_select_id()= 0; virtual int get_select_id()= 0;
/*
TRUE means this is a derived table. FALSE means otherwise.
*/
bool is_derived_table;
/* /*
A node may have children nodes. When a node's explain structure is 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 ids.
...@@ -494,6 +501,7 @@ class Explain_table_access : public Sql_alloc ...@@ -494,6 +501,7 @@ class Explain_table_access : public Sql_alloc
{ {
public: public:
Explain_table_access() : Explain_table_access() :
derived_select_number(0),
where_cond(NULL), where_cond(NULL),
cache_cond(NULL), cache_cond(NULL),
pushed_index_cond(NULL) pushed_index_cond(NULL)
...@@ -512,6 +520,12 @@ class Explain_table_access : public Sql_alloc ...@@ -512,6 +520,12 @@ class Explain_table_access : public Sql_alloc
/* id and 'select_type' are cared-of by the parent Explain_select */ /* id and 'select_type' are cared-of by the parent Explain_select */
StringBuffer<32> table_name; StringBuffer<32> table_name;
/*
Non-zero number means this is a derived table. The number can be used to
find the query plan for the derived table
*/
int derived_select_number;
enum join_type type; enum join_type type;
StringBuffer<32> used_partitions; StringBuffer<32> used_partitions;
...@@ -581,7 +595,8 @@ class Explain_table_access : public Sql_alloc ...@@ -581,7 +595,8 @@ class Explain_table_access : public Sql_alloc
bool is_analyze, bool is_analyze,
uint select_id, const char *select_type, uint select_id, const char *select_type,
bool using_temporary, bool using_filesort); bool using_temporary, bool using_filesort);
void print_explain_json(Json_writer *writer, bool is_analyze); void print_explain_json(Explain_query *query, Json_writer *writer,
bool is_analyze);
/* ANALYZE members*/ /* ANALYZE members*/
Table_access_tracker tracker; Table_access_tracker tracker;
......
...@@ -4268,6 +4268,8 @@ int st_select_lex_unit::save_union_explain(Explain_query *output) ...@@ -4268,6 +4268,8 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
{ {
SELECT_LEX *first= first_select(); SELECT_LEX *first= first_select();
Explain_union *eu= new (output->mem_root) Explain_union; Explain_union *eu= new (output->mem_root) Explain_union;
if (derived)
eu->is_derived_table= true;
for (SELECT_LEX *sl= first; sl; sl= sl->next_select()) for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
eu->add_select(sl->select_number); eu->add_select(sl->select_number);
......
...@@ -23654,6 +23654,12 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab ...@@ -23654,6 +23654,12 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
tab->cache->save_explain_data(&eta->bka_type); tab->cache->save_explain_data(&eta->bka_type);
} }
} }
/*
In case this is a derived table, here we remember the number of
subselect that used to produce it.
*/
eta->derived_select_number= table->derived_select_number;
} }
/* /*
...@@ -23686,6 +23692,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table, ...@@ -23686,6 +23692,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
xpl_sel->select_id= join->select_lex->select_number; xpl_sel->select_id= join->select_lex->select_number;
xpl_sel->select_type= join->select_lex->type; xpl_sel->select_type= join->select_lex->type;
xpl_sel->message= message; xpl_sel->message= message;
if (select_lex->master_unit()->derived)
xpl_sel->is_derived_table= true;
/* Setting xpl_sel->message means that all other members are invalid */ /* Setting xpl_sel->message means that all other members are invalid */
output->add_node(xpl_sel); output->add_node(xpl_sel);
} }
...@@ -23703,6 +23711,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table, ...@@ -23703,6 +23711,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
join->select_lex->set_explain_type(true); join->select_lex->set_explain_type(true);
xpl_sel->select_id= join->select_lex->select_number; xpl_sel->select_id= join->select_lex->select_number;
xpl_sel->select_type= join->select_lex->type; xpl_sel->select_type= join->select_lex->type;
if (select_lex->master_unit()->derived)
xpl_sel->is_derived_table= true;
JOIN_TAB* const first_top_tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS); JOIN_TAB* const first_top_tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment