Commit 00006950 authored by Sergei Petrunia's avatar Sergei Petrunia

EXPLAIN FORMAT=JSON

Add support for semi-join strategies: FirstMatch, DuplicateWeedout,
LooseScan.
parent a35b0539
...@@ -592,5 +592,77 @@ EXPLAIN ...@@ -592,5 +592,77 @@ EXPLAIN
} }
} }
} }
#
# First-Match
#
explain
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 10
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; FirstMatch(t2); Using join buffer (flat, BNL join)
explain format=json
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t2",
"access_type": "ALL",
"rows": 10,
"filtered": 100
},
"block-nl-join": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100,
"first_match": "t2"
},
"buffer_type": "flat",
"join_type": "BNL",
"attached_condition": "((t1.b = t2.b) and (t1.a = t2.a))"
}
}
}
#
# Duplicate Weedout
#
set @tmp= @@optimizer_switch;
set optimizer_switch='firstmatch=off';
explain
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 10
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
explain format=json
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t2",
"access_type": "ALL",
"rows": 10,
"filtered": 100
},
"duplicates_removal": {
"block-nl-join": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
},
"buffer_type": "flat",
"join_type": "BNL",
"attached_condition": "((t1.b = t2.b) and (t1.a = t2.a))"
}
}
}
}
set optimizer_switch=@tmp;
drop table t1,t2; drop table t1,t2;
drop table t0; drop table t0;
...@@ -114,6 +114,25 @@ insert into t2 select * from t1; ...@@ -114,6 +114,25 @@ insert into t2 select * from t1;
explain format=json explain format=json
select * from t1,t2 where t1.a in ( select a from t0); select * from t1,t2 where t1.a in ( select a from t0);
--echo #
--echo # First-Match
--echo #
explain
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
explain format=json
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
--echo #
--echo # Duplicate Weedout
--echo #
set @tmp= @@optimizer_switch;
set optimizer_switch='firstmatch=off';
explain
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
explain format=json
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
set optimizer_switch=@tmp;
drop table t1,t2; drop table t1,t2;
drop table t0; drop table t0;
...@@ -732,7 +732,13 @@ void Explain_basic_join::print_explain_json(Explain_query *query, ...@@ -732,7 +732,13 @@ void Explain_basic_join::print_explain_json(Explain_query *query,
writer->add_member("select_id").add_ll(select_id); writer->add_member("select_id").add_ll(select_id);
for (uint i=0; i< n_join_tabs; i++) for (uint i=0; i< n_join_tabs; i++)
{ {
if (join_tabs[i]->start_dups_weedout)
writer->add_member("duplicates_removal").start_object();
join_tabs[i]->print_explain_json(query, writer, is_analyze); join_tabs[i]->print_explain_json(query, writer, is_analyze);
if (join_tabs[i]->end_dups_weedout)
writer->end_object();
} }
print_explain_json_for_children(query, writer, is_analyze); print_explain_json_for_children(query, writer, is_analyze);
writer->end_object(); writer->end_object();
...@@ -1089,9 +1095,7 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -1089,9 +1095,7 @@ 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");
/* /*
We are printing the condition that is checked when scanning this We are printing the condition that is checked when scanning this
table. table.
...@@ -1099,7 +1103,11 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -1099,7 +1103,11 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
- in other cases, it is where_cond. - in other cases, it is where_cond.
*/ */
Item *item= bka_type.is_using_jbuf()? cache_cond: where_cond; Item *item= bka_type.is_using_jbuf()? cache_cond: where_cond;
write_item(writer, item); if (item)
{
writer->add_member("attached_condition");
write_item(writer, item);
}
} }
break; break;
case ET_USING_INDEX: case ET_USING_INDEX:
...@@ -1110,6 +1118,15 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -1110,6 +1118,15 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
break; break;
case ET_USING_JOIN_BUFFER: case ET_USING_JOIN_BUFFER:
/* Do nothing. Join buffer is handled differently */ /* Do nothing. Join buffer is handled differently */
case ET_START_TEMPORARY:
case ET_END_TEMPORARY:
/* Handled as "duplicates_removal: { ... } */
break;
case ET_FIRST_MATCH:
writer->add_member("first_match").add_str(firstmatch_table_name.c_ptr());
break;
case ET_LOOSESCAN:
writer->add_member("loose_scan").add_bool(true);
break; break;
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
......
...@@ -539,6 +539,8 @@ class Explain_table_access : public Sql_alloc ...@@ -539,6 +539,8 @@ class Explain_table_access : public Sql_alloc
Explain_table_access() : Explain_table_access() :
derived_select_number(0), derived_select_number(0),
non_merged_sjm_number(0), non_merged_sjm_number(0),
start_dups_weedout(false),
end_dups_weedout(false),
where_cond(NULL), where_cond(NULL),
cache_cond(NULL), cache_cond(NULL),
pushed_index_cond(NULL), pushed_index_cond(NULL),
...@@ -615,6 +617,9 @@ class Explain_table_access : public Sql_alloc ...@@ -615,6 +617,9 @@ class Explain_table_access : public Sql_alloc
EXPLAIN_BKA_TYPE bka_type; EXPLAIN_BKA_TYPE bka_type;
StringBuffer<32> firstmatch_table_name; StringBuffer<32> firstmatch_table_name;
bool start_dups_weedout;
bool end_dups_weedout;
/* /*
Note: lifespan of WHERE condition is less than lifespan of this object. Note: lifespan of WHERE condition is less than lifespan of this object.
......
...@@ -23641,9 +23641,16 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab ...@@ -23641,9 +23641,16 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
} }
if (tab->first_weedout_table) if (tab->first_weedout_table)
{
eta->start_dups_weedout= true;
eta->push_extra(ET_START_TEMPORARY); eta->push_extra(ET_START_TEMPORARY);
}
if (tab->check_weed_out_table) if (tab->check_weed_out_table)
{
eta->push_extra(ET_END_TEMPORARY); eta->push_extra(ET_END_TEMPORARY);
eta->end_dups_weedout= true;
}
else if (tab->do_firstmatch) else if (tab->do_firstmatch)
{ {
if (tab->do_firstmatch == /*join->join_tab*/ first_top_tab - 1) if (tab->do_firstmatch == /*join->join_tab*/ first_top_tab - 1)
......
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