Commit a80a7976 authored by Sergei Petrunia's avatar Sergei Petrunia

EXPLAIN FORMAT=JSON: Support "range checked for each record"

parent 9cac7649
...@@ -691,5 +691,31 @@ EXPLAIN ...@@ -691,5 +691,31 @@ EXPLAIN
} }
} }
} }
# 'Range checked for each record'
set optimizer_switch=@tmp;
explain format=json
select * from t1 tbl1, t1 tbl2 where tbl2.a < tbl1.b;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "tbl1",
"access_type": "ALL",
"rows": 100,
"filtered": 100
},
"range-checked-for-each-record": {
"keys": ["a"],
"table": {
"table_name": "tbl2",
"access_type": "ALL",
"possible_keys": ["a"],
"rows": 100,
"filtered": 100
}
}
}
}
drop table t1; drop table t1;
drop table t0; drop table t0;
...@@ -145,6 +145,11 @@ set optimizer_switch='mrr=on,mrr_sort_keys=on'; ...@@ -145,6 +145,11 @@ set optimizer_switch='mrr=on,mrr_sort_keys=on';
explain format=json select * from t1 where a < 3; explain format=json select * from t1 where a < 3;
--echo # 'Range checked for each record'
set optimizer_switch=@tmp;
explain format=json
select * from t1 tbl1, t1 tbl2 where tbl2.a < tbl1.b;
drop table t1; drop table t1;
drop table t0; drop table t0;
...@@ -1132,6 +1132,8 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -1132,6 +1132,8 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
case ET_USING: case ET_USING:
// index merge: case ET_USING // index merge: case ET_USING
break; break;
case ET_RANGE_CHECKED_FOR_EACH_RECORD:
/* Handled as range_checked_fer */
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_START_TEMPORARY:
...@@ -1153,6 +1155,22 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t ...@@ -1153,6 +1155,22 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
} }
static
void add_json_keyset(Json_writer *writer, const char *elem_name,
String_list *keyset)
{
if (!keyset->is_empty())
{
List_iterator_fast<char> it(*keyset);
const char *name;
writer->add_member(elem_name).start_array();
while ((name= it++))
writer->add_str(name);
writer->end_array();
}
}
void Explain_table_access::print_explain_json(Explain_query *query, void Explain_table_access::print_explain_json(Explain_query *query,
Json_writer *writer, Json_writer *writer,
bool is_analyze) bool is_analyze)
...@@ -1164,20 +1182,19 @@ void Explain_table_access::print_explain_json(Explain_query *query, ...@@ -1164,20 +1182,19 @@ void Explain_table_access::print_explain_json(Explain_query *query,
writer->add_member("block-nl-join").start_object(); writer->add_member("block-nl-join").start_object();
} }
if (range_checked_fer)
{
writer->add_member("range-checked-for-each-record").start_object();
add_json_keyset(writer, "keys", &possible_keys);
}
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);
// partitions // partitions
writer->add_member("access_type").add_str(join_type_str[type]); writer->add_member("access_type").add_str(join_type_str[type]);
if (!possible_keys.is_empty())
{ add_json_keyset(writer, "possible_keys", &possible_keys);
List_iterator_fast<char> it(possible_keys);
const char *name;
writer->add_member("possible_keys").start_array();
while ((name= it++))
writer->add_str(name);
writer->end_array();
}
/* `key` */ /* `key` */
/* For non-basic quick select, 'key' will not be present */ /* For non-basic quick select, 'key' will not be present */
...@@ -1272,9 +1289,12 @@ void Explain_table_access::print_explain_json(Explain_query *query, ...@@ -1272,9 +1289,12 @@ void Explain_table_access::print_explain_json(Explain_query *query,
tag_to_json(writer, extra_tags.at(i)); tag_to_json(writer, extra_tags.at(i));
} }
if (range_checked_fer)
writer->end_object(); // "range-checked-for-each-record"
if (bka_type.is_using_jbuf()) if (bka_type.is_using_jbuf())
{ {
writer->end_object(); writer->end_object(); // "block-nl-join"
writer->add_member("buffer_type").add_str(bka_type.incremental? writer->add_member("buffer_type").add_str(bka_type.incremental?
"incremental":"flat"); "incremental":"flat");
writer->add_member("join_type").add_str(bka_type.join_alg); writer->add_member("join_type").add_str(bka_type.join_alg);
...@@ -1388,7 +1408,7 @@ void Explain_table_access::append_tag_name(String *str, enum explain_extra_tag t ...@@ -1388,7 +1408,7 @@ void Explain_table_access::append_tag_name(String *str, enum explain_extra_tag t
char buf[MAX_KEY / 4 + 1]; char buf[MAX_KEY / 4 + 1];
str->append(STRING_WITH_LEN("Range checked for each " str->append(STRING_WITH_LEN("Range checked for each "
"record (index map: 0x")); "record (index map: 0x"));
str->append(range_checked_map.print(buf)); str->append(range_checked_fer->keys_map.print(buf));
str->append(')'); str->append(')');
break; break;
} }
......
...@@ -538,6 +538,18 @@ private: ...@@ -538,6 +538,18 @@ private:
}; };
/*
Data structure for "range checked for each record".
It's a set of keys, tabular explain prints hex bitmap, json prints key names.
*/
class Explain_range_checked_fer : public Sql_alloc
{
public:
String_list key_set;
key_map keys_map;
};
/* /*
EXPLAIN data structure for a single JOIN_TAB. EXPLAIN data structure for a single JOIN_TAB.
*/ */
...@@ -549,6 +561,7 @@ public: ...@@ -549,6 +561,7 @@ public:
derived_select_number(0), derived_select_number(0),
non_merged_sjm_number(0), non_merged_sjm_number(0),
extra_tags(root), extra_tags(root),
range_checked_fer(NULL),
start_dups_weedout(false), start_dups_weedout(false),
end_dups_weedout(false), end_dups_weedout(false),
where_cond(NULL), where_cond(NULL),
...@@ -619,8 +632,8 @@ public: ...@@ -619,8 +632,8 @@ public:
// Valid if ET_USING tag is present // Valid if ET_USING tag is present
Explain_quick_select *quick_info; Explain_quick_select *quick_info;
// valid with ET_RANGE_CHECKED_FOR_EACH_RECORD /* Non-NULL values means this tab uses "range checked for each record" */
key_map range_checked_map; Explain_range_checked_fer *range_checked_fer;
// valid with ET_USING_JOIN_BUFFER // valid with ET_USING_JOIN_BUFFER
EXPLAIN_BKA_TYPE bka_type; EXPLAIN_BKA_TYPE bka_type;
......
...@@ -23574,7 +23574,10 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab ...@@ -23574,7 +23574,10 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
if (tab->use_quick == 2) if (tab->use_quick == 2)
{ {
eta->push_extra(ET_RANGE_CHECKED_FOR_EACH_RECORD); eta->push_extra(ET_RANGE_CHECKED_FOR_EACH_RECORD);
eta->range_checked_map= tab->keys; eta->range_checked_fer= new (thd->mem_root) Explain_range_checked_fer;
eta->range_checked_fer->keys_map= tab->keys;
append_possible_keys(thd->mem_root, eta->range_checked_fer->key_set,
table, tab->keys);
} }
else if (tab->select->cond || else if (tab->select->cond ||
(tab->cache_select && tab->cache_select->cond)) (tab->cache_select && tab->cache_select->cond))
......
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