diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2015-07-01 20:03:29 +0300 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2015-07-01 20:03:29 +0300 |
commit | 9d2aa2b3093e315f02e42943589f47447c67bbd8 (patch) | |
tree | f2f73397e7d6b26e76971e702fbd6a6a01b95521 | |
parent | c6aee27b73232fc6ba3e8b55adbb0abba4f0171b (diff) | |
download | mariadb-git-9d2aa2b3093e315f02e42943589f47447c67bbd8.tar.gz |
MDEV-7811: EXPLAIN/ANALYZE FORMAT=JSON should show subquery cache
Fixes over the original patch:
- Fix variable/class/other names
- Fix the JSON output to be in line with the output of other JSON
constructs we produce
-rw-r--r-- | mysql-test/r/subselect_cache.result | 235 | ||||
-rw-r--r-- | sql/item.cc | 12 | ||||
-rw-r--r-- | sql/item.h | 4 | ||||
-rw-r--r-- | sql/item_subselect.cc | 15 | ||||
-rw-r--r-- | sql/item_subselect.h | 2 | ||||
-rw-r--r-- | sql/sql_explain.cc | 44 | ||||
-rw-r--r-- | sql/sql_explain.h | 6 | ||||
-rw-r--r-- | sql/sql_expression_cache.cc | 18 | ||||
-rw-r--r-- | sql/sql_expression_cache.h | 34 |
9 files changed, 191 insertions, 179 deletions
diff --git a/mysql-test/r/subselect_cache.result b/mysql-test/r/subselect_cache.result index 2cf1961ec5b..8ca6bf52e0e 100644 --- a/mysql-test/r/subselect_cache.result +++ b/mysql-test/r/subselect_cache.result @@ -59,27 +59,24 @@ ANALYZE }, "subqueries": [ { - "query_block": { - "select_id": 2, - "r_loops": 4, - "r_total_time_ms": "REPLACED", - "expression_cache": { - "state": "ENABLED", - "r_hit": 6, - "r_miss": 4, - "r_loops": 10, - "r_hit_ratio": 60 - }, - "table": { - "table_name": "t2", - "access_type": "ALL", + "expression_cache": { + "r_loops": 10, + "r_hit_ratio": 60, + "query_block": { + "select_id": 2, "r_loops": 4, - "rows": 4, - "r_rows": 4, "r_total_time_ms": "REPLACED", - "filtered": 100, - "r_filtered": 18.75, - "attached_condition": "(t1.b = t2.c)" + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 4, + "rows": 4, + "r_rows": 4, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 18.75, + "attached_condition": "(t1.b = t2.c)" + } } } } @@ -106,72 +103,66 @@ ANALYZE }, "subqueries": [ { - "query_block": { - "union_result": { - "table_name": "<union3,4>", - "access_type": "ALL", - "r_loops": 4, - "r_rows": 1, - "expression_cache": { - "state": "ENABLED", - "r_hit": 6, - "r_miss": 4, - "r_loops": 10, - "r_hit_ratio": 60 - }, - "query_specifications": [ - { - "query_block": { - "select_id": 3, - "r_loops": 4, - "r_total_time_ms": "REPLACED", - "table": { - "table_name": "t2", - "access_type": "ALL", + "expression_cache": { + "r_loops": 10, + "r_hit_ratio": 60, + "query_block": { + "union_result": { + "table_name": "<union3,4>", + "access_type": "ALL", + "r_loops": 4, + "r_rows": 1, + "query_specifications": [ + { + "query_block": { + "select_id": 3, "r_loops": 4, - "rows": 4, - "r_rows": 4, "r_total_time_ms": "REPLACED", - "filtered": 100, - "r_filtered": 18.75, - "attached_condition": "(t1.b = t2.c)" + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 4, + "rows": 4, + "r_rows": 4, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 18.75, + "attached_condition": "(t1.b = t2.c)" + } } - } - }, - { - "query_block": { - "select_id": 4, - "table": { - "message": "No tables used" + }, + { + "query_block": { + "select_id": 4, + "table": { + "message": "No tables used" + } } } - } - ] + ] + } } } }, { - "query_block": { - "select_id": 2, - "r_loops": 4, - "r_total_time_ms": "REPLACED", - "expression_cache": { - "state": "ENABLED", - "r_hit": 6, - "r_miss": 4, - "r_loops": 10, - "r_hit_ratio": 60 - }, - "table": { - "table_name": "t2", - "access_type": "ALL", + "expression_cache": { + "r_loops": 10, + "r_hit_ratio": 60, + "query_block": { + "select_id": 2, "r_loops": 4, - "rows": 4, - "r_rows": 4, "r_total_time_ms": "REPLACED", - "filtered": 100, - "r_filtered": 18.75, - "attached_condition": "(t1.b = t2.c)" + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 4, + "rows": 4, + "r_rows": 4, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 18.75, + "attached_condition": "(t1.b = t2.c)" + } } } } @@ -192,17 +183,17 @@ EXPLAIN }, "subqueries": [ { - "query_block": { - "select_id": 2, - "expression_cache": { - "state": "UNINITIALYZED" - }, - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 4, - "filtered": 100, - "attached_condition": "(t1.b = t2.c)" + "expression_cache": { + "state": "uninitialized", + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "(t1.b = t2.c)" + } } } } @@ -223,50 +214,50 @@ EXPLAIN }, "subqueries": [ { - "query_block": { - "union_result": { - "table_name": "<union3,4>", - "access_type": "ALL", - "expression_cache": { - "state": "UNINITIALYZED" - }, - "query_specifications": [ - { - "query_block": { - "select_id": 3, - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 4, - "filtered": 100, - "attached_condition": "(t1.b = t2.c)" + "expression_cache": { + "state": "uninitialized", + "query_block": { + "union_result": { + "table_name": "<union3,4>", + "access_type": "ALL", + "query_specifications": [ + { + "query_block": { + "select_id": 3, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "(t1.b = t2.c)" + } } - } - }, - { - "query_block": { - "select_id": 4, - "table": { - "message": "No tables used" + }, + { + "query_block": { + "select_id": 4, + "table": { + "message": "No tables used" + } } } - } - ] + ] + } } } }, { - "query_block": { - "select_id": 2, - "expression_cache": { - "state": "UNINITIALYZED" - }, - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 4, - "filtered": 100, - "attached_condition": "(t1.b = t2.c)" + "expression_cache": { + "state": "uninitialized", + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "(t1.b = t2.c)" + } } } } diff --git a/sql/item.cc b/sql/item.cc index 14e14968278..f8365226a76 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7554,15 +7554,15 @@ bool Item_cache_wrapper::set_cache(THD *thd) DBUG_RETURN(expr_cache == NULL); } -Expression_cache_stat* Item_cache_wrapper::set_stat(MEM_ROOT *mem_root) +Expression_cache_tracker* Item_cache_wrapper::init_tracker(MEM_ROOT *mem_root) { if (expr_cache) { - Expression_cache_stat* stat= - new(mem_root) Expression_cache_stat(expr_cache); - if (stat) - ((Expression_cache_tmptable *)expr_cache)->set_stat(stat); - return stat; + Expression_cache_tracker* tracker= + new(mem_root) Expression_cache_tracker(expr_cache); + if (tracker) + ((Expression_cache_tmptable *)expr_cache)->set_tracker(tracker); + return tracker; } return NULL; } diff --git a/sql/item.h b/sql/item.h index cecc0f24514..88c02a67f9b 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3804,7 +3804,7 @@ public: class Item_cache; class Expression_cache; -class Expression_cache_stat; +class Expression_cache_tracker; /** The objects of this class can store its values in an expression cache. @@ -3839,7 +3839,7 @@ public: enum Type real_type() const { return orig_item->type(); } bool set_cache(THD *thd); - Expression_cache_stat* set_stat(MEM_ROOT *mem_root); + Expression_cache_tracker* init_tracker(MEM_ROOT *mem_root); bool fix_fields(THD *thd, Item **it); void cleanup(); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 0b90063f9cb..fa2549a0bd5 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1202,7 +1202,7 @@ Item* Item_singlerow_subselect::expr_cache_insert_transformer(uchar *thd_arg) if (expr_cache_is_needed(thd) && (expr_cache= set_expr_cache(thd))) { - set_expr_cache_stat(thd); + init_expr_cache_tracker(thd); DBUG_RETURN(expr_cache); } DBUG_RETURN(this); @@ -1501,7 +1501,7 @@ Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg) if (substype() == EXISTS_SUBS && expr_cache_is_needed(thd) && (expr_cache= set_expr_cache(thd))) { - set_expr_cache_stat(thd); + init_expr_cache_tracker(thd); DBUG_RETURN(expr_cache); } DBUG_RETURN(this); @@ -6562,7 +6562,13 @@ void subselect_table_scan_engine::cleanup() { } -void Item_subselect::set_expr_cache_stat(THD *thd) + +/* + Create an execution tracker for the expression cache we're using for this + subselect; add the tracker to the query plan. +*/ + +void Item_subselect::init_expr_cache_tracker(THD *thd) { if(!expr_cache) return; @@ -6573,5 +6579,6 @@ void Item_subselect::set_expr_cache_stat(THD *thd) if (!node) return; DBUG_ASSERT(expr_cache->type() == Item::EXPR_CACHE_ITEM); - node->cache_stat= ((Item_cache_wrapper *)expr_cache)->set_stat(qw->mem_root); + node->cache_tracker= ((Item_cache_wrapper *)expr_cache)->init_tracker(qw->mem_root); } + diff --git a/sql/item_subselect.h b/sql/item_subselect.h index cad66cd3442..1930493b6b9 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -246,7 +246,7 @@ public: return TRUE; } - void set_expr_cache_stat(THD *thd); + void init_expr_cache_tracker(THD *thd); friend class select_result_interceptor; diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 210700a2804..9f4b635fbf4 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -521,6 +521,8 @@ void Explain_union::print_explain_json(Explain_query *query, Json_writer_nesting_guard guard(writer); char table_name_buffer[SAFE_NAME_LEN]; + bool started_object= print_explain_json_cache(writer, is_analyze); + writer->add_member("query_block").start_object(); writer->add_member("union_result").start_object(); // using_temporary_table @@ -544,7 +546,6 @@ void Explain_union::print_explain_json(Explain_query *query, writer->add_null(); } - print_explain_json_cache(writer, is_analyze); writer->add_member("query_specifications").start_array(); for (int i= 0; i < (int) union_members.elements(); i++) @@ -562,6 +563,9 @@ void Explain_union::print_explain_json(Explain_query *query, writer->end_object(); // union_result writer->end_object(); // query_block + + if (started_object) + writer->end_object(); } @@ -642,27 +646,32 @@ void Explain_node::print_explain_json_for_children(Explain_query *query, } -void Explain_node::print_explain_json_cache(Json_writer *writer, +bool Explain_node::print_explain_json_cache(Json_writer *writer, bool is_analyze) { - if (cache_stat) + if (cache_tracker) + { + cache_tracker->fetch_current_stats(); + writer->add_member("expression_cache").start_object(); + if (cache_tracker->state != Expression_cache_tracker::OK) { - cache_stat->flush_stat(); - writer->add_member("expression_cache").start_object(); writer->add_member("state"). - add_str(Expression_cache_stat::state_str[cache_stat->state]); - if (is_analyze) + add_str(Expression_cache_tracker::state_str[cache_tracker->state]); + } + + if (is_analyze) + { + longlong cache_reads= cache_tracker->hit + cache_tracker->miss; + writer->add_member("r_loops").add_ll(cache_reads); + if (cache_reads != 0) { - writer->add_member("r_hit").add_ll(cache_stat->hit); - writer->add_member("r_miss").add_ll(cache_stat->miss); - writer->add_member("r_loops").add_ll(cache_stat->hit + - cache_stat->miss); - writer->add_member("r_hit_ratio").add_ll(((double)cache_stat->hit)/ - ((double)(cache_stat->hit + - cache_stat->miss)) * 100.0); + double hit_ratio= double(cache_tracker->hit) / cache_reads * 100.0; + writer->add_member("r_hit_ratio").add_double(hit_ratio); } - writer->end_object(); } + return true; + } + return false; } @@ -766,6 +775,8 @@ void Explain_select::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) { Json_writer_nesting_guard guard(writer); + + bool started_cache= print_explain_json_cache(writer, is_analyze); if (message) { @@ -795,7 +806,6 @@ void Explain_select::print_explain_json(Explain_query *query, writer->add_member("const_condition"); write_item(writer, exec_const_cond); } - print_explain_json_cache(writer, is_analyze); Filesort_tracker *first_table_sort= NULL; bool first_table_sort_used= false; @@ -887,6 +897,8 @@ void Explain_select::print_explain_json(Explain_query *query, writer->end_object(); } + if (started_cache) + writer->end_object(); } diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 427553c1088..1b6a1be5649 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -85,7 +85,7 @@ class Explain_node : public Sql_alloc { public: Explain_node(MEM_ROOT *root) : - cache_stat(NULL), + cache_tracker(NULL), connection_type(EXPLAIN_NODE_OTHER), children(root) {} @@ -113,7 +113,7 @@ public: /** expression cache statistics */ - Expression_cache_stat* cache_stat; + Expression_cache_tracker* cache_tracker; /* How this node is connected to its parent. @@ -140,7 +140,7 @@ public: uint8 explain_flags, bool is_analyze); void print_explain_json_for_children(Explain_query *query, Json_writer *writer, bool is_analyze); - void print_explain_json_cache(Json_writer *writer, bool is_analyze); + bool print_explain_json_cache(Json_writer *writer, bool is_analyze); virtual ~Explain_node(){} }; diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc index bda0aaafebe..cc922c3bcfe 100644 --- a/sql/sql_expression_cache.cc +++ b/sql/sql_expression_cache.cc @@ -43,7 +43,7 @@ ulong subquery_cache_miss, subquery_cache_hit; Expression_cache_tmptable::Expression_cache_tmptable(THD *thd, List<Item> &dependants, Item *value) - :cache_table(NULL), table_thd(thd), stat(NULL), items(dependants), val(value), + :cache_table(NULL), table_thd(thd), tracker(NULL), items(dependants), val(value), hit(0), miss(0), inited (0) { DBUG_ENTER("Expression_cache_tmptable::Expression_cache_tmptable"); @@ -61,9 +61,9 @@ void Expression_cache_tmptable::disable_cache() cache_table->file->ha_index_end(); free_tmp_table(table_thd, cache_table); cache_table= NULL; - flush_stat(); - if (stat) - stat->cache= NULL; + update_tracker(); + if (tracker) + tracker->cache= NULL; } @@ -167,7 +167,7 @@ void Expression_cache_tmptable::init() goto error; } - flush_stat(); + update_tracker(); DBUG_VOID_RETURN; error: @@ -186,8 +186,8 @@ Expression_cache_tmptable::~Expression_cache_tmptable() disable_cache(); else { - flush_stat(); - stat= NULL; + update_tracker(); + tracker= NULL; } } @@ -334,5 +334,5 @@ void Expression_cache_tmptable::print(String *str, enum_query_type query_type) } -const char *Expression_cache_stat::state_str[3]= -{"UNINITIALYZED", "DISABLED", "ENABLED"}; +const char *Expression_cache_tracker::state_str[3]= +{"uninitialized", "disabled", "enabled"}; diff --git a/sql/sql_expression_cache.h b/sql/sql_expression_cache.h index 33c67f8eaca..87be6ddb4f4 100644 --- a/sql/sql_expression_cache.h +++ b/sql/sql_expression_cache.h @@ -65,9 +65,9 @@ public: virtual void init()= 0; /** - Save this object's statistics into Expression_cache_stat object + Save this object's statistics into Expression_cache_tracker object */ - virtual void flush_stat()= 0; + virtual void update_tracker()= 0; }; struct st_table_ref; @@ -75,11 +75,11 @@ struct st_join_table; class Item_field; -class Expression_cache_stat :public Sql_alloc +class Expression_cache_tracker :public Sql_alloc { public: enum expr_cache_state {UNINITED, STOPPED, OK}; - Expression_cache_stat(Expression_cache *c) : + Expression_cache_tracker(Expression_cache *c) : cache(c), hit(0), miss(0), state(UNINITED) {} @@ -91,10 +91,10 @@ public: void set(ulong h, ulong m, enum expr_cache_state s) {hit= h; miss= m; state= s;} - void flush_stat() + void fetch_current_stats() { if (cache) - cache->flush_stat(); + cache->update_tracker(); } }; @@ -115,18 +115,20 @@ public: bool is_inited() { return inited; }; void init(); - void set_stat(Expression_cache_stat *st) + void set_tracker(Expression_cache_tracker *st) { - stat= st; - flush_stat(); + tracker= st; + update_tracker(); } - virtual void flush_stat() + virtual void update_tracker() { - if (stat) - stat->set(hit, miss, (inited ? (cache_table ? - Expression_cache_stat::OK : - Expression_cache_stat::STOPPED) : - Expression_cache_stat::UNINITED)); + if (tracker) + { + tracker->set(hit, miss, (inited ? (cache_table ? + Expression_cache_tracker::OK : + Expression_cache_tracker::STOPPED) : + Expression_cache_tracker::UNINITED)); + } } private: @@ -139,7 +141,7 @@ private: /* Thread handle for the temporary table */ THD *table_thd; /* EXPALIN/ANALYZE statistics */ - Expression_cache_stat *stat; + Expression_cache_tracker *tracker; /* TABLE_REF for index lookup */ struct st_table_ref ref; /* Cached result */ |