Commit 2078392c authored by Sergei Petrunia's avatar Sergei Petrunia

Make EXPLAIN FORMAT=JSON be able to show the key that's used for sorting.

This will be useful for window functions development.
parent 9b5951c3
......@@ -490,6 +490,7 @@ ANALYZE
"volatile parameter": "REPLACED",
"having_condition": "(TOP > t2.a)",
"filesort": {
"sort_key": "t2.a",
"r_loops": 1,
"volatile parameter": "REPLACED",
"r_used_priority_queue": false,
......@@ -519,6 +520,7 @@ ANALYZE
"r_loops": 1,
"volatile parameter": "REPLACED",
"filesort": {
"sort_key": "t2.a",
"r_loops": 1,
"volatile parameter": "REPLACED",
"r_used_priority_queue": false,
......@@ -559,6 +561,7 @@ ANALYZE
"r_loops": 1,
"volatile parameter": "REPLACED",
"filesort": {
"sort_key": "t2.a",
"r_loops": 1,
"volatile parameter": "REPLACED",
"r_used_priority_queue": false,
......@@ -680,6 +683,7 @@ ANALYZE
"r_loops": 1,
"volatile parameter": "REPLACED",
"filesort": {
"sort_key": "group_concat(t3.f3 separator ',')",
"r_loops": 1,
"volatile parameter": "REPLACED",
"r_used_priority_queue": false,
......@@ -687,6 +691,7 @@ ANALYZE
"volatile parameter": "REPLACED",
"temporary_table": {
"filesort": {
"sort_key": "(subquery#2)",
"r_loops": 1,
"volatile parameter": "REPLACED",
"r_used_priority_queue": false,
......
......@@ -172,6 +172,7 @@ EXPLAIN
"query_block": {
"select_id": 1,
"filesort": {
"sort_key": "t2.b",
"temporary_table": {
"table": {
"table_name": "t0",
......@@ -204,6 +205,7 @@ ANALYZE
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"filesort": {
"sort_key": "t2.b",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"r_limit": 4,
......@@ -256,6 +258,7 @@ EXPLAIN
"select_id": 1,
"read_sorted_file": {
"filesort": {
"sort_key": "t0.a",
"table": {
"table_name": "t0",
"access_type": "ALL",
......@@ -289,6 +292,7 @@ ANALYZE
"read_sorted_file": {
"r_rows": 10,
"filesort": {
"sort_key": "t0.a",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"r_used_priority_queue": false,
......@@ -345,6 +349,7 @@ ANALYZE
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"filesort": {
"sort_key": "t2.c",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"r_used_priority_queue": false,
......@@ -454,6 +459,7 @@ ANALYZE
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"filesort": {
"sort_key": "count(distinct t5.b)",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"r_limit": 1,
......@@ -461,6 +467,7 @@ ANALYZE
"r_output_rows": 2,
"temporary_table": {
"filesort": {
"sort_key": "t5.a",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"r_used_priority_queue": false,
......@@ -510,8 +517,10 @@ EXPLAIN
"query_block": {
"select_id": 1,
"filesort": {
"sort_key": "count(distinct t5.b)",
"temporary_table": {
"filesort": {
"sort_key": "t5.a",
"temporary_table": {
"table": {
"table_name": "t6",
......
......@@ -486,6 +486,7 @@ EXPLAIN
"query_block": {
"select_id": 2,
"filesort": {
"sort_key": "t1.a",
"temporary_table": {
"table": {
"table_name": "t1",
......@@ -529,6 +530,7 @@ EXPLAIN
"query_block": {
"select_id": 2,
"filesort": {
"sort_key": "t1.a",
"temporary_table": {
"table": {
"table_name": "t1",
......@@ -1129,6 +1131,7 @@ EXPLAIN
"select_id": 1,
"having_condition": "(TOP > t2.a)",
"filesort": {
"sort_key": "t2.a",
"temporary_table": {
"table": {
"table_name": "t2",
......@@ -1147,6 +1150,7 @@ EXPLAIN
"query_block": {
"select_id": 1,
"filesort": {
"sort_key": "t2.a",
"temporary_table": {
"table": {
"table_name": "t2",
......@@ -1176,6 +1180,7 @@ EXPLAIN
"query_block": {
"select_id": 1,
"filesort": {
"sort_key": "t2.a",
"temporary_table": {
"table": {
"table_name": "t2",
......
......@@ -1436,6 +1436,7 @@ EXPLAIN
"query_block": {
"select_id": 1,
"filesort": {
"sort_key": "t1.a",
"window_functions_computation": {
"temporary_table": {
"table": {
......@@ -1488,6 +1489,7 @@ EXPLAIN
"select_id": 1,
"having_condition": "(MX in (3,5,7))",
"filesort": {
"sort_key": "t1.b",
"window_functions_computation": {
"temporary_table": {
"table": {
......
......@@ -30,6 +30,7 @@ const char * STR_IMPOSSIBLE_WHERE= "Impossible WHERE";
const char * STR_NO_ROWS_AFTER_PRUNING= "No matching rows after partition pruning";
static void write_item(Json_writer *writer, Item *item);
static void append_item_to_str(String *out, Item *item);
Explain_query::Explain_query(THD *thd_arg, MEM_ROOT *root) :
mem_root(root), upd_del_plan(NULL), insert_plan(NULL),
......@@ -877,8 +878,7 @@ void Explain_select::print_explain_json(Explain_query *query,
case AGGR_OP_FILESORT:
{
writer->add_member("filesort").start_object();
if (is_analyze)
((Explain_aggr_filesort*)node)->tracker->print_json_members(writer);
((Explain_aggr_filesort*)node)->print_json_members(writer, is_analyze);
break;
}
case AGGR_OP_REMOVE_DUPLICATES:
......@@ -905,6 +905,41 @@ void Explain_select::print_explain_json(Explain_query *query,
writer->end_object();
}
void Explain_aggr_filesort::init(THD *thd, Filesort *filesort)
{
for (ORDER *ord= filesort->order; ord; ord= ord->next)
{
sort_items.push_back(ord->item[0], thd->mem_root);
}
filesort->tracker= &tracker;
}
void Explain_aggr_filesort::print_json_members(Json_writer *writer,
bool is_analyze)
{
char item_buf[256];
String str(item_buf, sizeof(item_buf), &my_charset_bin);
str.length(0);
List_iterator_fast<Item> it(sort_items);
Item *item;
bool first= true;
while ((item= it++))
{
if (first)
first= false;
else
{
str.append(", ");
}
append_item_to_str(&str, item);
}
writer->add_member("sort_key").add_str(str.c_ptr_safe());
if (is_analyze)
tracker.print_json_members(writer);
}
void Explain_basic_join::print_explain_json(Explain_query *query,
Json_writer *writer,
......@@ -1222,7 +1257,7 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai
extra_buf.append(STRING_WITH_LEN("Using temporary"));
}
if (using_filesort || this->using_filesort)
if (using_filesort || this->pre_join_sort)
{
if (first)
first= false;
......@@ -1282,6 +1317,15 @@ static void write_item(Json_writer *writer, Item *item)
writer->add_str(str.c_ptr_safe());
}
static void append_item_to_str(String *out, Item *item)
{
THD *thd= current_thd;
ulonglong save_option_bits= thd->variables.option_bits;
thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE;
item->print(out, QT_EXPLAIN);
thd->variables.option_bits= save_option_bits;
}
void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_tag tag)
{
......@@ -1409,15 +1453,6 @@ void add_json_keyset(Json_writer *writer, const char *elem_name,
print_json_array(writer, elem_name, *keyset);
}
/*
@param fs_tracker Normally NULL. When not NULL, it means that the join tab
used filesort to pre-sort the data. Then, sorted data
was read and the rest of the join was executed.
@note
EXPLAIN command will check whether fs_tracker is present, but it can't use
any value from fs_tracker (these are only valid for ANALYZE).
*/
void Explain_table_access::print_explain_json(Explain_query *query,
Json_writer *writer,
......@@ -1425,7 +1460,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
{
Json_writer_nesting_guard guard(writer);
if (using_filesort)
if (pre_join_sort)
{
/* filesort was invoked on this join tab before doing the join with the rest */
writer->add_member("read_sorted_file").start_object();
......@@ -1452,9 +1487,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
}
}
writer->add_member("filesort").start_object();
if (is_analyze)
fs_tracker->print_json_members(writer);
pre_join_sort->print_json_members(writer, is_analyze);
}
if (bka_type.is_using_jbuf())
......@@ -1532,11 +1565,11 @@ void Explain_table_access::print_explain_json(Explain_query *query,
if (is_analyze)
{
writer->add_member("r_rows");
if (fs_tracker)
if (pre_join_sort)
{
/* Get r_rows value from filesort */
if (fs_tracker->get_r_loops())
writer->add_double(fs_tracker->get_avg_examined_rows());
if (pre_join_sort->tracker.get_r_loops())
writer->add_double(pre_join_sort->tracker.get_avg_examined_rows());
else
writer->add_null();
}
......@@ -1563,11 +1596,11 @@ void Explain_table_access::print_explain_json(Explain_query *query,
if (is_analyze)
{
writer->add_member("r_filtered");
if (fs_tracker)
if (pre_join_sort)
{
/* Get r_filtered value from filesort */
if (fs_tracker->get_r_loops())
writer->add_double(fs_tracker->get_r_filtered());
if (pre_join_sort->tracker.get_r_loops())
writer->add_double(pre_join_sort->tracker.get_r_filtered());
else
writer->add_null();
}
......@@ -1645,7 +1678,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
writer->end_object();
}
if (using_filesort)
if (pre_join_sort)
{
writer->end_object(); // filesort
writer->end_object(); // read_sorted_file
......
......@@ -281,9 +281,18 @@ class Explain_aggr_node : public Sql_alloc
class Explain_aggr_filesort : public Explain_aggr_node
{
List<Item> sort_items;
public:
enum_explain_aggr_node_type get_type() { return AGGR_OP_FILESORT; }
Filesort_tracker *tracker;
Filesort_tracker tracker;
Explain_aggr_filesort(bool is_analyze) : tracker(is_analyze)
{
child= NULL;
}
void init(THD* thd, Filesort *filesort);
void print_json_members(Json_writer *writer, bool is_analyze);
};
class Explain_aggr_tmp_table : public Explain_aggr_node
......@@ -663,8 +672,7 @@ class Explain_table_access : public Sql_alloc
cache_cond(NULL),
pushed_index_cond(NULL),
sjm_nest(NULL),
using_filesort(false),
fs_tracker(NULL)
pre_join_sort(NULL)
{}
~Explain_table_access() { delete sjm_nest; }
......@@ -757,9 +765,13 @@ class Explain_table_access : public Sql_alloc
Item *pushed_index_cond;
Explain_basic_join *sjm_nest;
bool using_filesort;
Filesort_tracker *fs_tracker;
/*
This describes a possible filesort() call that is done before doing the
join operation.
*/
Explain_aggr_filesort *pre_join_sort;
/* ANALYZE members */
/* Tracker for reading the table */
......
......@@ -23746,7 +23746,6 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
explain_plan= eta;
eta->key.clear();
eta->quick_info= NULL;
eta->using_filesort= false;
SQL_SELECT *tab_select;
/*
......@@ -23758,9 +23757,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
if (filesort)
{
eta->using_filesort= true; // This fixes EXPLAIN
eta->fs_tracker= filesort->tracker=
new Filesort_tracker(thd->lex->analyze_stmt);
eta->pre_join_sort= new Explain_aggr_filesort(thd->lex->analyze_stmt);
eta->pre_join_sort->init(thd, filesort);
}
tracker= &eta->tracker;
......@@ -24201,9 +24199,9 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
if (join_tab->filesort)
{
Explain_aggr_filesort *eaf = new Explain_aggr_filesort;
eaf->tracker= new Filesort_tracker(join->thd->lex->analyze_stmt);
join_tab->filesort->tracker= eaf->tracker;
bool is_analyze= join->thd->lex->analyze_stmt;
Explain_aggr_filesort *eaf = new Explain_aggr_filesort(is_analyze);
eaf->init(join->thd, join_tab->filesort);
prev_node= node;
node= eaf;
......
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