diff options
Diffstat (limited to '')
-rw-r--r-- | sql/sql_explain.cc | 168 |
1 files changed, 161 insertions, 7 deletions
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 210f229a..b8c9c87c 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -36,6 +36,11 @@ const char *unit_operation_text[4]= "UNIT RESULT","UNION RESULT","INTERSECT RESULT","EXCEPT RESULT" }; +const char *pushed_unit_operation_text[4]= +{ + "PUSHED UNIT", "PUSHED UNION", "PUSHED INTERSECT", "PUSHED EXCEPT" +}; + const char *pushed_derived_text= "PUSHED DERIVED"; const char *pushed_select_text= "PUSHED SELECT"; @@ -575,7 +580,22 @@ uint Explain_union::make_union_table_name(char *buf) } -int Explain_union::print_explain(Explain_query *query, +int Explain_union::print_explain(Explain_query *query, + select_result_sink *output, + uint8 explain_flags, bool is_analyze) +{ + if (is_pushed_down_to_engine) + return print_explain_pushed_down(output, explain_flags, is_analyze); + else + return print_explain_regular(query, output, explain_flags, is_analyze); +} + +/* + Prints EXPLAIN plan for a regular UNIT (UNION/EXCEPT/INTERSECT), + i.e. UNIT that has not been pushed down to a storage engine +*/ + +int Explain_union::print_explain_regular(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) @@ -592,7 +612,15 @@ int Explain_union::print_explain(Explain_query *query, } if (!using_tmp) + { + /* + The union operation may not employ a temporary table, for example, + for UNION ALL, in that case the results of the query are sent directly + to the output. So there is no actual UNION operation and we don't need + to print the line in the EXPLAIN output. + */ return 0; + } /* Print a line with "UNIT RESULT" */ List<Item> item_list; @@ -609,7 +637,7 @@ int Explain_union::print_explain(Explain_query *query, item_list.push_back(new (mem_root) Item_string_sys(thd, table_name_buffer, len), mem_root); - + /* `partitions` column */ if (explain_flags & DESCRIBE_PARTITIONS) item_list.push_back(item_null, mem_root); @@ -665,7 +693,6 @@ int Explain_union::print_explain(Explain_query *query, extra_buf.length()), mem_root); - //output->unit.offset_limit_cnt= 0; if (output->send_data(item_list)) return 1; @@ -677,9 +704,89 @@ int Explain_union::print_explain(Explain_query *query, } -void Explain_union::print_explain_json(Explain_query *query, +/* + Prints EXPLAIN plan for a UNIT (UNION/EXCEPT/INTERSECT) that + has been pushed down to a storage engine +*/ + +int Explain_union::print_explain_pushed_down(select_result_sink *output, + uint8 explain_flags, + bool is_analyze) +{ + THD *thd= output->thd; + MEM_ROOT *mem_root= thd->mem_root; + List<Item> item_list; + Item *item_null= new (mem_root) Item_null(thd); + + /* `id` column */ + item_list.push_back(item_null, mem_root); + + /* `select_type` column */ + push_str(thd, &item_list, fake_select_type); + + /* `table` column */ + item_list.push_back(item_null, mem_root); + + /* `partitions` column */ + if (explain_flags & DESCRIBE_PARTITIONS) + item_list.push_back(item_null, mem_root); + + /* `type` column */ + item_list.push_back(item_null, mem_root); + + /* `possible_keys` column */ + item_list.push_back(item_null, mem_root); + + /* `key` */ + item_list.push_back(item_null, mem_root); + + /* `key_len` */ + item_list.push_back(item_null, mem_root); + + /* `ref` */ + item_list.push_back(item_null, mem_root); + + /* `rows` */ + item_list.push_back(item_null, mem_root); + + /* `r_rows` */ + if (is_analyze) + item_list.push_back(item_null, mem_root); + + /* `filtered` */ + if (explain_flags & DESCRIBE_EXTENDED || is_analyze) + item_list.push_back(item_null, mem_root); + + /* `r_filtered` */ + if (is_analyze) + item_list.push_back(item_null, mem_root); + + /* `Extra` */ + item_list.push_back(item_null, mem_root); + + if (output->send_data(item_list)) + return 1; + return 0; +} + + +void Explain_union::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) { + if (is_pushed_down_to_engine) + print_explain_json_pushed_down(query, writer, is_analyze); + else + print_explain_json_regular(query, writer, is_analyze); +} + +/* + Prints EXPLAIN plan in JSON format for a regular UNIT (UNION/EXCEPT/INTERSECT), + i.e. UNIT that has not been pushed down to a storage engine +*/ + +void Explain_union::print_explain_json_regular( + Explain_query *query, Json_writer *writer, bool is_analyze) +{ Json_writer_nesting_guard guard(writer); char table_name_buffer[SAFE_NAME_LEN]; @@ -737,6 +844,30 @@ void Explain_union::print_explain_json(Explain_query *query, writer->end_object(); } +/* + Prints EXPLAIN plan in JSON format for a UNIT (UNION/EXCEPT/INTERSECT) that + has been pushed down to a storage engine +*/ + +void Explain_union::print_explain_json_pushed_down(Explain_query *query, + Json_writer *writer, + bool is_analyze) +{ + Json_writer_nesting_guard guard(writer); + + writer->add_member("query_block").start_object(); + + if (is_recursive_cte) + writer->add_member("recursive_union").start_object(); + else + writer->add_member("union_result").start_object(); + + writer->add_member("message").add_str(fake_select_type); + + writer->end_object(); // union_result + writer->end_object(); // query_block +} + /* Print EXPLAINs for all children nodes (i.e. for subqueries) @@ -1028,6 +1159,9 @@ void Explain_select::print_explain_json(Explain_query *query, writer->add_member("select_id").add_ll(select_id); add_linkage(writer); + if (cost != 0.0) + writer->add_member("cost").add_double(cost); + if (is_analyze && time_tracker.get_loops()) { writer->add_member("r_loops").add_ll(time_tracker.get_loops()); @@ -1371,10 +1505,12 @@ double Explain_table_access::get_r_filtered() } -int Explain_table_access::print_explain(select_result_sink *output, uint8 explain_flags, +int Explain_table_access::print_explain(select_result_sink *output, + uint8 explain_flags, bool is_analyze, uint select_id, const char *select_type, - bool using_temporary, bool using_filesort) + bool using_temporary, + bool using_filesort) { THD *thd= output->thd; // note: for SHOW EXPLAIN, this is target thd. MEM_ROOT *mem_root= thd->mem_root; @@ -1921,10 +2057,21 @@ void Explain_table_access::print_explain_json(Explain_query *query, rowid_filter->print_explain_json(query, writer, is_analyze); } + if (loops != 0.0) + writer->add_member("loops").add_double(loops); + /* r_loops (not present in tabular output) */ if (is_analyze) { - writer->add_member("r_loops").add_ll(tracker.get_loops()); + ha_rows loops= tracker.get_loops(); + writer->add_member("r_loops").add_ll(loops); + + if (type == JT_EQ_REF) // max one row + { + ha_rows table_loops= op_tracker.get_loops(); + if (table_loops != loops) + writer->add_member("r_table_loops").add_ll(table_loops); + } } /* `rows` */ @@ -1950,7 +2097,13 @@ void Explain_table_access::print_explain_json(Explain_query *query, else writer->add_null(); } + } + + if (cost != 0.0) + writer->add_member("cost").add_double(cost); + if (is_analyze) + { if (op_tracker.get_loops()) { double total_time= op_tracker.get_time_ms(); @@ -2050,6 +2203,7 @@ void Explain_table_access::print_explain_json(Explain_query *query, } else writer->add_null(); + } } |