Commit 7b988e5c authored by Varun Gupta's avatar Varun Gupta

MDEV-20444: More information regarding access of a table to be printed inside the optimizer_trace

Added:
      1) estimated_join_cardinality
      2) best_chosen_access_method for a table
      3) best_join_order
parent e980cf91
This diff is collapsed.
......@@ -207,18 +207,29 @@ explain select * from t1 where a=1 or b=1 {
"best_access_path": {
"considered_access_paths": [
{
"access_type": "range",
"access_type": "index_merge",
"resulting_rows": 2,
"cost": 4.1484,
"chosen": true
}
]
],
"chosen_access_method": {
"type": "index_merge",
"records": 2,
"cost": 4.1484,
"uses_join_buffering": false,
"filter_used": false
}
},
"rows_for_plan": 2,
"cost_for_plan": 4.5484
"cost_for_plan": 4.5484,
"estimated_join_cardinality": 2
}
]
},
{
"best_join_order": ["t1"]
},
{
"attaching_conditions_to_tables": {
"original_condition": "t1.a = 1 or t1.b = 1",
......
......@@ -208,13 +208,24 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"chosen": false,
"cause": "cost"
}
]
],
"chosen_access_method": {
"type": "ref",
"records": 1,
"cost": 2,
"uses_join_buffering": false,
"filter_used": false
}
},
"rows_for_plan": 1,
"cost_for_plan": 2.2
"cost_for_plan": 2.2,
"estimated_join_cardinality": 1
}
]
},
{
"best_join_order": ["t1"]
},
{
"attaching_conditions_to_tables": {
"original_condition": "t1.key1 = 1 and t1.pk1 <> 0",
......
......@@ -98,13 +98,24 @@ select * from db1.t1 {
"cost": 2.0051,
"chosen": true
}
]
],
"chosen_access_method": {
"type": "scan",
"records": 3,
"cost": 2.0051,
"uses_join_buffering": false,
"filter_used": false
}
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051
"cost_for_plan": 2.6051,
"estimated_join_cardinality": 3
}
]
},
{
"best_join_order": ["t1"]
},
{
"attaching_conditions_to_tables": {
"original_condition": null,
......@@ -211,13 +222,24 @@ select * from db1.v1 {
"cost": 2.0051,
"chosen": true
}
]
],
"chosen_access_method": {
"type": "scan",
"records": 3,
"cost": 2.0051,
"uses_join_buffering": false,
"filter_used": false
}
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051
"cost_for_plan": 2.6051,
"estimated_join_cardinality": 3
}
]
},
{
"best_join_order": ["t1"]
},
{
"attaching_conditions_to_tables": {
"original_condition": null,
......
......@@ -630,6 +630,45 @@ void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab)
table_rec.add("rows", tab->found_records)
.add("cost", tab->read_time);
}
/*
Print the join order of all the tables for top level select.
For example:
select * from ot1
where ot1.a IN (select it1.a from it1, it2 where it1.b=it2.a);
So this function would print
ot1, <subquery2> ----> For select #1
*/
void print_final_join_order(JOIN *join)
{
Json_writer_object join_order(join->thd);
Json_writer_array best_order(join->thd, "best_join_order");
JOIN_TAB *j;
uint i;
for (j= join->join_tab,i=0 ; i < join->top_join_tab_count;
i++, j++)
best_order.add_table_name(j);
}
void print_best_access_for_table(THD *thd, POSITION *pos,
enum join_type type)
{
Json_writer_object trace_best_access(thd, "chosen_access_method");
trace_best_access.add("type", type == JT_ALL ? "scan" :
join_type_str[type]);
trace_best_access.add("records", pos->records_read);
trace_best_access.add("cost", pos->read_time);
trace_best_access.add("uses_join_buffering", pos->use_join_buffer);
trace_best_access.add("filter_used",
pos->range_rowid_filter_info != NULL);
}
/*
Introduce enum_query_type flags parameter, maybe also allow
EXPLAIN also use this function.
......
......@@ -105,6 +105,9 @@ void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
Json_writer_object *trace_object);
void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab);
void print_final_join_order(JOIN *join);
void print_best_access_for_table(THD *thd, POSITION *pos,
enum join_type type);
/*
Security related (need to add a proper comment here)
......
......@@ -7203,6 +7203,7 @@ best_access_path(JOIN *join,
SplM_plan_info *spl_plan= 0;
Range_rowid_filter_cost_info *filter= 0;
const char* cause= NULL;
enum join_type best_type= JT_UNKNOWN, type= JT_UNKNOWN;
disable_jbuf= disable_jbuf || idx == join->const_tables;
......@@ -7342,7 +7343,8 @@ best_access_path(JOIN *join,
*/
tmp= prev_record_reads(join->positions, idx, found_ref);
records= 1.0;
trace_access_idx.add("access_type", "fulltext")
type= JT_FT;
trace_access_idx.add("access_type", join_type_str[type])
.add("index", keyinfo->name);
}
else
......@@ -7365,14 +7367,16 @@ best_access_path(JOIN *join,
(!(key_flags & HA_NULL_PART_KEY) || // (2)
all_key_parts == notnull_part)) // (3)
{
trace_access_idx.add("access_type", "eq_ref")
type= JT_EQ_REF;
trace_access_idx.add("access_type", join_type_str[type])
.add("index", keyinfo->name);
tmp = prev_record_reads(join->positions, idx, found_ref);
records=1.0;
}
else
{
trace_access_idx.add("access_type", "ref")
type= JT_REF;
trace_access_idx.add("access_type", join_type_str[type])
.add("index", keyinfo->name);
if (!found_ref)
{ /* We found a const key */
......@@ -7467,8 +7471,8 @@ best_access_path(JOIN *join,
}
else
{
trace_access_idx.add("access_type",
ref_or_null_part ? "ref_or_null" : "ref")
type = ref_or_null_part ? JT_REF_OR_NULL : JT_REF;
trace_access_idx.add("access_type", join_type_str[type])
.add("index", keyinfo->name);
/*
Use as much key-parts as possible and a uniq key is better
......@@ -7683,6 +7687,7 @@ best_access_path(JOIN *join,
best_max_key_part= max_key_part;
best_ref_depends_map= found_ref;
best_filter= filter;
best_type= type;
}
else
{
......@@ -7736,6 +7741,7 @@ best_access_path(JOIN *join,
best_ref_depends_map= 0;
best_uses_jbuf= TRUE;
best_filter= 0;
best_type= JT_HASH;
trace_access_hash.add("type", "hash");
trace_access_hash.add("index", "hj-key");
trace_access_hash.add("cost", rnd_records);
......@@ -7799,10 +7805,6 @@ best_access_path(JOIN *join,
filter= 0;
if (s->quick)
{
trace_access_scan.add("access_type", "range");
/*
should have some info about all the different QUICK_SELECT
*/
/*
For each record we:
- read record range through 'quick'
......@@ -7828,23 +7830,29 @@ best_access_path(JOIN *join,
{
tmp-= filter->get_adjusted_gain(rows);
DBUG_ASSERT(tmp >= 0);
}
}
type= JT_RANGE;
}
else
{
type= JT_INDEX_MERGE;
best_filter= 0;
}
loose_scan_opt.check_range_access(join, idx, s->quick);
}
else
{
trace_access_scan.add("access_type", "scan");
/* Estimate cost of reading table. */
if (s->table->force_index && !best_key) // index scan
{
type= JT_NEXT;
tmp= s->table->file->read_time(s->ref.key, 1, s->records);
}
else // table scan
{
tmp= s->scan_time();
type= JT_ALL;
}
if ((s->table->map & join->outer_join) || disable_jbuf) // Can't use join cache
{
......@@ -7874,6 +7882,9 @@ best_access_path(JOIN *join,
}
}
trace_access_scan.add("access_type", type == JT_ALL ?
"scan" :
join_type_str[type]);
/* Splitting technique cannot be used with join cache */
if (s->table->is_splittable())
tmp+= s->table->get_materialization_cost();
......@@ -7913,6 +7924,7 @@ best_access_path(JOIN *join,
best_uses_jbuf= MY_TEST(!disable_jbuf && !((s->table->map &
join->outer_join)));
spl_plan= 0;
best_type= type;
}
trace_access_scan.add("chosen", best_key == NULL);
}
......@@ -7944,6 +7956,11 @@ best_access_path(JOIN *join,
trace_access_scan.add("use_tmp_table", true);
join->sort_by_table= (TABLE*) 1; // Must use temporary table
}
trace_access_scan.end();
trace_paths.end();
if (unlikely(thd->trace_started()))
print_best_access_for_table(thd, pos, best_type);
DBUG_VOID_RETURN;
}
......@@ -9484,6 +9501,8 @@ best_extension_by_limited_search(JOIN *join,
Hence it may be wrong.
*/
current_read_time= COST_ADD(current_read_time, current_record_count);
trace_one_table.add("estimated_join_cardinality",
partial_join_cardinality);
if (current_read_time < join->best_read)
{
memcpy((uchar*) join->best_positions, (uchar*) join->positions,
......@@ -10305,6 +10324,9 @@ bool JOIN::get_best_combination()
top_join_tab_count= (uint)(join_tab_ranges.head()->end -
join_tab_ranges.head()->start);
if (unlikely(thd->trace_started()))
print_final_join_order(this);
update_depend_map(this);
DBUG_RETURN(0);
}
......
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