mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
EXPLAIN FORMAT=JSON: Support "range checked for each record"
This commit is contained in:
@ -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';
|
|||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,
|
|||||||
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,
|
|||||||
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
|
|||||||
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:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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:
|
|||||||
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:
|
|||||||
// 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
|
|||||||
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))
|
||||||
|
Reference in New Issue
Block a user