Commit 461dbd80 authored by Sergei Petrunia's avatar Sergei Petrunia

EXPLAIN FORMAT=JSON: support join buffering

- Basic support for JOIN buffering
- The output is not polished but catches the main point:
  tab->select_cond and tab->cache_select->cond are printed separately.
- Hash join support is poor still.

- Also fixed identation in JOIN_TAB::save_explain_data
parent 37c444e1
...@@ -309,4 +309,37 @@ EXPLAIN ...@@ -309,4 +309,37 @@ EXPLAIN
} }
} }
drop table t1; drop table t1;
#
# Join buffering
#
create table t1 (a int, b int);
insert into t1 select A.a+10*B.a, A.a+10*B.a from t0 A, t0 B;
explain format=json
select * from t1 A, t1 B where A.a=B.a and A.b < 3 and B.b < 5;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "A",
"access_type": "ALL",
"rows": 100,
"filtered": 100,
"attached_condition": "(A.b < 3)"
},
"block-nl-join": {
"table": {
"table_name": "B",
"access_type": "ALL",
"rows": 100,
"filtered": 100,
"attached_condition": "(B.b < 5)"
},
"buffer_type": "flat",
"join_type": "BNL",
"attached_condition": "(B.a = A.a)"
}
}
}
drop table t1;
drop table t0; drop table t0;
...@@ -58,5 +58,17 @@ select * from t0 where ...@@ -58,5 +58,17 @@ select * from t0 where
a > (select max(b) from t1 where t1.b=t0.a) or a < 3 ; a > (select max(b) from t1 where t1.b=t0.a) or a < 3 ;
drop table t1; drop table t1;
--echo #
--echo # Join buffering
--echo #
create table t1 (a int, b int);
insert into t1 select A.a+10*B.a, A.a+10*B.a from t0 A, t0 B;
explain format=json
select * from t1 A, t1 B where A.a=B.a and A.b < 3 and B.b < 5;
drop table t1;
drop table t0; drop table t0;
...@@ -903,8 +903,18 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -903,8 +903,18 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
write_item(writer, pushed_index_cond); write_item(writer, pushed_index_cond);
break; break;
case ET_USING_WHERE: case ET_USING_WHERE:
if (where_cond)
{
writer->add_member("attached_condition"); writer->add_member("attached_condition");
write_item(writer, where_cond); /*
We are printing the condition that is checked when scanning this
table.
- when join buffer is used, it is cache_cond.
- in other cases, it is where_cond.
*/
Item *item= bka_type.is_using_jbuf()? cache_cond: where_cond;
write_item(writer, item);
}
break; break;
case ET_USING_INDEX: case ET_USING_INDEX:
writer->add_member("using_index").add_bool(true); writer->add_member("using_index").add_bool(true);
...@@ -913,7 +923,7 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -913,7 +923,7 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
// index merge: case ET_USING // index merge: case ET_USING
break; break;
case ET_USING_JOIN_BUFFER: case ET_USING_JOIN_BUFFER:
// TODO TODO /* Do nothing. Join buffer is handled differently */
break; break;
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -925,6 +935,12 @@ void Explain_table_access::print_explain_json(Json_writer *writer, ...@@ -925,6 +935,12 @@ void Explain_table_access::print_explain_json(Json_writer *writer,
bool is_analyze) bool is_analyze)
{ {
Json_writer_nesting_guard guard(writer); Json_writer_nesting_guard guard(writer);
if (bka_type.is_using_jbuf())
{
writer->add_member("block-nl-join").start_object();
}
writer->add_member("table").start_object(); writer->add_member("table").start_object();
writer->add_member("table_name").add_str(table_name); writer->add_member("table_name").add_str(table_name);
...@@ -1018,6 +1034,21 @@ void Explain_table_access::print_explain_json(Json_writer *writer, ...@@ -1018,6 +1034,21 @@ void Explain_table_access::print_explain_json(Json_writer *writer,
tag_to_json(writer, extra_tags.at(i)); tag_to_json(writer, extra_tags.at(i));
} }
if (bka_type.is_using_jbuf())
{
writer->end_object();
writer->add_member("buffer_type").add_str(bka_type.incremental?
"incremental":"flat");
writer->add_member("join_type").add_str(bka_type.join_alg);
if (bka_type.mrr_type.length())
writer->add_member("mrr_type").add_str(bka_type.mrr_type);
if (where_cond)
{
writer->add_member("attached_condition");
write_item(writer, where_cond);
}
}
writer->end_object(); writer->end_object();
} }
......
...@@ -488,6 +488,12 @@ private: ...@@ -488,6 +488,12 @@ private:
class Explain_table_access : public Sql_alloc class Explain_table_access : public Sql_alloc
{ {
public: public:
Explain_table_access() :
where_cond(NULL),
cache_cond(NULL),
pushed_index_cond(NULL)
{}
void push_extra(enum explain_extra_tag extra_tag); void push_extra(enum explain_extra_tag extra_tag);
/* Internals */ /* Internals */
...@@ -558,9 +564,12 @@ public: ...@@ -558,9 +564,12 @@ public:
/* /*
Note: lifespan of WHERE condition is less than lifespan of this object. Note: lifespan of WHERE condition is less than lifespan of this object.
THe below is valid if tags include "ET_USING_WHERE". The below two are valid if tags include "ET_USING_WHERE".
(TODO: indexsubquery may put ET_USING_WHERE without setting where_cond?)
*/ */
Item *where_cond; Item *where_cond;
Item *cache_cond;
Item *pushed_index_cond; Item *pushed_index_cond;
int print_explain(select_result_sink *output, uint8 explain_flags, int print_explain(select_result_sink *output, uint8 explain_flags,
......
...@@ -23684,8 +23684,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab ...@@ -23684,8 +23684,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
} }
else else
{ {
eta->where_cond= tab->select->cond? tab->select->cond: eta->where_cond= tab->select->cond;
tab->cache_select->cond; eta->cache_cond= tab->cache_select? tab->cache_select->cond : NULL;
eta->push_extra(ET_USING_WHERE); eta->push_extra(ET_USING_WHERE);
} }
} }
......
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