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 ...@@ -490,6 +490,7 @@ ANALYZE
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"having_condition": "(TOP > t2.a)", "having_condition": "(TOP > t2.a)",
"filesort": { "filesort": {
"sort_key": "t2.a",
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
...@@ -519,6 +520,7 @@ ANALYZE ...@@ -519,6 +520,7 @@ ANALYZE
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"filesort": { "filesort": {
"sort_key": "t2.a",
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
...@@ -559,6 +561,7 @@ ANALYZE ...@@ -559,6 +561,7 @@ ANALYZE
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"filesort": { "filesort": {
"sort_key": "t2.a",
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
...@@ -680,6 +683,7 @@ ANALYZE ...@@ -680,6 +683,7 @@ ANALYZE
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"filesort": { "filesort": {
"sort_key": "group_concat(t3.f3 separator ',')",
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
...@@ -687,6 +691,7 @@ ANALYZE ...@@ -687,6 +691,7 @@ ANALYZE
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"temporary_table": { "temporary_table": {
"filesort": { "filesort": {
"sort_key": "(subquery#2)",
"r_loops": 1, "r_loops": 1,
"volatile parameter": "REPLACED", "volatile parameter": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
......
...@@ -172,6 +172,7 @@ EXPLAIN ...@@ -172,6 +172,7 @@ EXPLAIN
"query_block": { "query_block": {
"select_id": 1, "select_id": 1,
"filesort": { "filesort": {
"sort_key": "t2.b",
"temporary_table": { "temporary_table": {
"table": { "table": {
"table_name": "t0", "table_name": "t0",
...@@ -204,6 +205,7 @@ ANALYZE ...@@ -204,6 +205,7 @@ ANALYZE
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"filesort": { "filesort": {
"sort_key": "t2.b",
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"r_limit": 4, "r_limit": 4,
...@@ -256,6 +258,7 @@ EXPLAIN ...@@ -256,6 +258,7 @@ EXPLAIN
"select_id": 1, "select_id": 1,
"read_sorted_file": { "read_sorted_file": {
"filesort": { "filesort": {
"sort_key": "t0.a",
"table": { "table": {
"table_name": "t0", "table_name": "t0",
"access_type": "ALL", "access_type": "ALL",
...@@ -289,6 +292,7 @@ ANALYZE ...@@ -289,6 +292,7 @@ ANALYZE
"read_sorted_file": { "read_sorted_file": {
"r_rows": 10, "r_rows": 10,
"filesort": { "filesort": {
"sort_key": "t0.a",
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
...@@ -345,6 +349,7 @@ ANALYZE ...@@ -345,6 +349,7 @@ ANALYZE
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"filesort": { "filesort": {
"sort_key": "t2.c",
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
...@@ -454,6 +459,7 @@ ANALYZE ...@@ -454,6 +459,7 @@ ANALYZE
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"filesort": { "filesort": {
"sort_key": "count(distinct t5.b)",
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"r_limit": 1, "r_limit": 1,
...@@ -461,6 +467,7 @@ ANALYZE ...@@ -461,6 +467,7 @@ ANALYZE
"r_output_rows": 2, "r_output_rows": 2,
"temporary_table": { "temporary_table": {
"filesort": { "filesort": {
"sort_key": "t5.a",
"r_loops": 1, "r_loops": 1,
"r_total_time_ms": "REPLACED", "r_total_time_ms": "REPLACED",
"r_used_priority_queue": false, "r_used_priority_queue": false,
...@@ -510,8 +517,10 @@ EXPLAIN ...@@ -510,8 +517,10 @@ EXPLAIN
"query_block": { "query_block": {
"select_id": 1, "select_id": 1,
"filesort": { "filesort": {
"sort_key": "count(distinct t5.b)",
"temporary_table": { "temporary_table": {
"filesort": { "filesort": {
"sort_key": "t5.a",
"temporary_table": { "temporary_table": {
"table": { "table": {
"table_name": "t6", "table_name": "t6",
......
...@@ -486,6 +486,7 @@ EXPLAIN ...@@ -486,6 +486,7 @@ EXPLAIN
"query_block": { "query_block": {
"select_id": 2, "select_id": 2,
"filesort": { "filesort": {
"sort_key": "t1.a",
"temporary_table": { "temporary_table": {
"table": { "table": {
"table_name": "t1", "table_name": "t1",
...@@ -529,6 +530,7 @@ EXPLAIN ...@@ -529,6 +530,7 @@ EXPLAIN
"query_block": { "query_block": {
"select_id": 2, "select_id": 2,
"filesort": { "filesort": {
"sort_key": "t1.a",
"temporary_table": { "temporary_table": {
"table": { "table": {
"table_name": "t1", "table_name": "t1",
...@@ -1129,6 +1131,7 @@ EXPLAIN ...@@ -1129,6 +1131,7 @@ EXPLAIN
"select_id": 1, "select_id": 1,
"having_condition": "(TOP > t2.a)", "having_condition": "(TOP > t2.a)",
"filesort": { "filesort": {
"sort_key": "t2.a",
"temporary_table": { "temporary_table": {
"table": { "table": {
"table_name": "t2", "table_name": "t2",
...@@ -1147,6 +1150,7 @@ EXPLAIN ...@@ -1147,6 +1150,7 @@ EXPLAIN
"query_block": { "query_block": {
"select_id": 1, "select_id": 1,
"filesort": { "filesort": {
"sort_key": "t2.a",
"temporary_table": { "temporary_table": {
"table": { "table": {
"table_name": "t2", "table_name": "t2",
...@@ -1176,6 +1180,7 @@ EXPLAIN ...@@ -1176,6 +1180,7 @@ EXPLAIN
"query_block": { "query_block": {
"select_id": 1, "select_id": 1,
"filesort": { "filesort": {
"sort_key": "t2.a",
"temporary_table": { "temporary_table": {
"table": { "table": {
"table_name": "t2", "table_name": "t2",
......
...@@ -1436,6 +1436,7 @@ EXPLAIN ...@@ -1436,6 +1436,7 @@ EXPLAIN
"query_block": { "query_block": {
"select_id": 1, "select_id": 1,
"filesort": { "filesort": {
"sort_key": "t1.a",
"window_functions_computation": { "window_functions_computation": {
"temporary_table": { "temporary_table": {
"table": { "table": {
...@@ -1488,6 +1489,7 @@ EXPLAIN ...@@ -1488,6 +1489,7 @@ EXPLAIN
"select_id": 1, "select_id": 1,
"having_condition": "(MX in (3,5,7))", "having_condition": "(MX in (3,5,7))",
"filesort": { "filesort": {
"sort_key": "t1.b",
"window_functions_computation": { "window_functions_computation": {
"temporary_table": { "temporary_table": {
"table": { "table": {
......
...@@ -30,6 +30,7 @@ const char * STR_IMPOSSIBLE_WHERE= "Impossible WHERE"; ...@@ -30,6 +30,7 @@ const char * STR_IMPOSSIBLE_WHERE= "Impossible WHERE";
const char * STR_NO_ROWS_AFTER_PRUNING= "No matching rows after partition pruning"; const char * STR_NO_ROWS_AFTER_PRUNING= "No matching rows after partition pruning";
static void write_item(Json_writer *writer, Item *item); 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) : Explain_query::Explain_query(THD *thd_arg, MEM_ROOT *root) :
mem_root(root), upd_del_plan(NULL), insert_plan(NULL), mem_root(root), upd_del_plan(NULL), insert_plan(NULL),
...@@ -877,8 +878,7 @@ void Explain_select::print_explain_json(Explain_query *query, ...@@ -877,8 +878,7 @@ void Explain_select::print_explain_json(Explain_query *query,
case AGGR_OP_FILESORT: case AGGR_OP_FILESORT:
{ {
writer->add_member("filesort").start_object(); writer->add_member("filesort").start_object();
if (is_analyze) ((Explain_aggr_filesort*)node)->print_json_members(writer, is_analyze);
((Explain_aggr_filesort*)node)->tracker->print_json_members(writer);
break; break;
} }
case AGGR_OP_REMOVE_DUPLICATES: case AGGR_OP_REMOVE_DUPLICATES:
...@@ -905,6 +905,41 @@ void Explain_select::print_explain_json(Explain_query *query, ...@@ -905,6 +905,41 @@ void Explain_select::print_explain_json(Explain_query *query,
writer->end_object(); 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, void Explain_basic_join::print_explain_json(Explain_query *query,
Json_writer *writer, Json_writer *writer,
...@@ -1222,7 +1257,7 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai ...@@ -1222,7 +1257,7 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai
extra_buf.append(STRING_WITH_LEN("Using temporary")); extra_buf.append(STRING_WITH_LEN("Using temporary"));
} }
if (using_filesort || this->using_filesort) if (using_filesort || this->pre_join_sort)
{ {
if (first) if (first)
first= false; first= false;
...@@ -1282,6 +1317,15 @@ static void write_item(Json_writer *writer, Item *item) ...@@ -1282,6 +1317,15 @@ static void write_item(Json_writer *writer, Item *item)
writer->add_str(str.c_ptr_safe()); 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) 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, ...@@ -1409,15 +1453,6 @@ void add_json_keyset(Json_writer *writer, const char *elem_name,
print_json_array(writer, elem_name, *keyset); 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, void Explain_table_access::print_explain_json(Explain_query *query,
Json_writer *writer, Json_writer *writer,
...@@ -1425,7 +1460,7 @@ void Explain_table_access::print_explain_json(Explain_query *query, ...@@ -1425,7 +1460,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
{ {
Json_writer_nesting_guard guard(writer); 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 */ /* filesort was invoked on this join tab before doing the join with the rest */
writer->add_member("read_sorted_file").start_object(); writer->add_member("read_sorted_file").start_object();
...@@ -1452,9 +1487,7 @@ void Explain_table_access::print_explain_json(Explain_query *query, ...@@ -1452,9 +1487,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
} }
} }
writer->add_member("filesort").start_object(); writer->add_member("filesort").start_object();
pre_join_sort->print_json_members(writer, is_analyze);
if (is_analyze)
fs_tracker->print_json_members(writer);
} }
if (bka_type.is_using_jbuf()) if (bka_type.is_using_jbuf())
...@@ -1532,11 +1565,11 @@ void Explain_table_access::print_explain_json(Explain_query *query, ...@@ -1532,11 +1565,11 @@ void Explain_table_access::print_explain_json(Explain_query *query,
if (is_analyze) if (is_analyze)
{ {
writer->add_member("r_rows"); writer->add_member("r_rows");
if (fs_tracker) if (pre_join_sort)
{ {
/* Get r_rows value from filesort */ /* Get r_rows value from filesort */
if (fs_tracker->get_r_loops()) if (pre_join_sort->tracker.get_r_loops())
writer->add_double(fs_tracker->get_avg_examined_rows()); writer->add_double(pre_join_sort->tracker.get_avg_examined_rows());
else else
writer->add_null(); writer->add_null();
} }
...@@ -1563,11 +1596,11 @@ void Explain_table_access::print_explain_json(Explain_query *query, ...@@ -1563,11 +1596,11 @@ void Explain_table_access::print_explain_json(Explain_query *query,
if (is_analyze) if (is_analyze)
{ {
writer->add_member("r_filtered"); writer->add_member("r_filtered");
if (fs_tracker) if (pre_join_sort)
{ {
/* Get r_filtered value from filesort */ /* Get r_filtered value from filesort */
if (fs_tracker->get_r_loops()) if (pre_join_sort->tracker.get_r_loops())
writer->add_double(fs_tracker->get_r_filtered()); writer->add_double(pre_join_sort->tracker.get_r_filtered());
else else
writer->add_null(); writer->add_null();
} }
...@@ -1645,7 +1678,7 @@ void Explain_table_access::print_explain_json(Explain_query *query, ...@@ -1645,7 +1678,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
writer->end_object(); writer->end_object();
} }
if (using_filesort) if (pre_join_sort)
{ {
writer->end_object(); // filesort writer->end_object(); // filesort
writer->end_object(); // read_sorted_file writer->end_object(); // read_sorted_file
......
...@@ -281,9 +281,18 @@ class Explain_aggr_node : public Sql_alloc ...@@ -281,9 +281,18 @@ class Explain_aggr_node : public Sql_alloc
class Explain_aggr_filesort : public Explain_aggr_node class Explain_aggr_filesort : public Explain_aggr_node
{ {
List<Item> sort_items;
public: public:
enum_explain_aggr_node_type get_type() { return AGGR_OP_FILESORT; } 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 class Explain_aggr_tmp_table : public Explain_aggr_node
...@@ -663,8 +672,7 @@ class Explain_table_access : public Sql_alloc ...@@ -663,8 +672,7 @@ class Explain_table_access : public Sql_alloc
cache_cond(NULL), cache_cond(NULL),
pushed_index_cond(NULL), pushed_index_cond(NULL),
sjm_nest(NULL), sjm_nest(NULL),
using_filesort(false), pre_join_sort(NULL)
fs_tracker(NULL)
{} {}
~Explain_table_access() { delete sjm_nest; } ~Explain_table_access() { delete sjm_nest; }
...@@ -757,9 +765,13 @@ class Explain_table_access : public Sql_alloc ...@@ -757,9 +765,13 @@ class Explain_table_access : public Sql_alloc
Item *pushed_index_cond; Item *pushed_index_cond;
Explain_basic_join *sjm_nest; 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 */ /* ANALYZE members */
/* Tracker for reading the table */ /* Tracker for reading the table */
......
...@@ -23746,7 +23746,6 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, ...@@ -23746,7 +23746,6 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
explain_plan= eta; explain_plan= eta;
eta->key.clear(); eta->key.clear();
eta->quick_info= NULL; eta->quick_info= NULL;
eta->using_filesort= false;
SQL_SELECT *tab_select; SQL_SELECT *tab_select;
/* /*
...@@ -23758,9 +23757,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, ...@@ -23758,9 +23757,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
if (filesort) if (filesort)
{ {
eta->using_filesort= true; // This fixes EXPLAIN eta->pre_join_sort= new Explain_aggr_filesort(thd->lex->analyze_stmt);
eta->fs_tracker= filesort->tracker= eta->pre_join_sort->init(thd, filesort);
new Filesort_tracker(thd->lex->analyze_stmt);
} }
tracker= &eta->tracker; tracker= &eta->tracker;
...@@ -24201,9 +24199,9 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel) ...@@ -24201,9 +24199,9 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
if (join_tab->filesort) if (join_tab->filesort)
{ {
Explain_aggr_filesort *eaf = new Explain_aggr_filesort; bool is_analyze= join->thd->lex->analyze_stmt;
eaf->tracker= new Filesort_tracker(join->thd->lex->analyze_stmt); Explain_aggr_filesort *eaf = new Explain_aggr_filesort(is_analyze);
join_tab->filesort->tracker= eaf->tracker; eaf->init(join->thd, join_tab->filesort);
prev_node= node; prev_node= node;
node= eaf; 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