Improved speed of optimizer trace

- Added unlikely() to optimize for not having optimizer trace enabled
- Made THD::trace_started() inline
- Added 'if (trace_enabled())' around some potentially expensive code
  (not many found)
- Added ASSERT's to ensure we don't call expensive optimizer trace calls
  if optimizer trace is not enabled
- Added length to Json_writer functions to speed up buffer writes
  when optimizer trace is enabled.
- Changed LEX_CSTRING argument handling to not send full struct to writer
  function on_add_str() functions now trusts length arguments
This commit is contained in:
Monty 2020-03-06 10:33:11 +02:00
parent 1ad8693a6f
commit 940fcbe73b
9 changed files with 176 additions and 102 deletions

View File

@ -79,7 +79,8 @@ void Json_writer::end_array()
Json_writer& Json_writer::add_member(const char *name)
{
if (fmt_helper.on_add_member(name))
size_t len= strlen(name);
if (fmt_helper.on_add_member(name, len))
return *this; // handled
// assert that we are in an object
@ -87,7 +88,22 @@ Json_writer& Json_writer::add_member(const char *name)
start_element();
output.append('"');
output.append(name);
output.append(name, len);
output.append("\": ", 3);
return *this;
}
Json_writer& Json_writer::add_member(const char *name, size_t len)
{
if (fmt_helper.on_add_member(name, len))
return *this; // handled
// assert that we are in an object
DBUG_ASSERT(!element_started);
start_element();
output.append('"');
output.append(name, len);
output.append("\": ");
return *this;
}
@ -141,28 +157,31 @@ void Json_writer::add_ull(ulonglong val)
void Json_writer::add_size(longlong val)
{
char buf[64];
size_t len;
if (val < 1024)
my_snprintf(buf, sizeof(buf), "%lld", val);
len= my_snprintf(buf, sizeof(buf), "%lld", val);
else if (val < 1024*1024*16)
{
/* Values less than 16MB are specified in KB for precision */
size_t len= my_snprintf(buf, sizeof(buf), "%lld", val/1024);
len= my_snprintf(buf, sizeof(buf), "%lld", val/1024);
strcpy(buf + len, "Kb");
len+= 2;
}
else
{
size_t len= my_snprintf(buf, sizeof(buf), "%lld", val/(1024*1024));
len= my_snprintf(buf, sizeof(buf), "%lld", val/(1024*1024));
strcpy(buf + len, "Mb");
len+= 2;
}
add_str(buf);
add_str(buf, len);
}
void Json_writer::add_double(double val)
{
char buf[64];
my_snprintf(buf, sizeof(buf), "%lg", val);
add_unquoted_str(buf);
size_t len= my_snprintf(buf, sizeof(buf), "%lg", val);
add_unquoted_str(buf, len);
}
@ -174,32 +193,46 @@ void Json_writer::add_bool(bool val)
void Json_writer::add_null()
{
add_unquoted_str("null");
add_unquoted_str("null", (size_t) 4);
}
void Json_writer::add_unquoted_str(const char* str)
{
if (fmt_helper.on_add_str(str, 0))
size_t len= strlen(str);
if (fmt_helper.on_add_str(str, len))
return;
if (!element_started)
start_element();
output.append(str);
output.append(str, len);
element_started= false;
}
void Json_writer::add_unquoted_str(const char* str, size_t len)
{
if (fmt_helper.on_add_str(str, len))
return;
if (!element_started)
start_element();
output.append(str, len);
element_started= false;
}
void Json_writer::add_str(const char *str)
{
if (fmt_helper.on_add_str(str, 0))
size_t len= strlen(str);
if (fmt_helper.on_add_str(str, len))
return;
if (!element_started)
start_element();
output.append('"');
output.append(str);
output.append(str, len);
output.append('"');
element_started= false;
}
@ -230,20 +263,20 @@ void Json_writer::add_str(const String &str)
Json_writer_object::Json_writer_object(THD *thd) :
Json_writer_struct(thd)
{
if (my_writer)
if (unlikely(my_writer))
my_writer->start_object();
}
Json_writer_object::Json_writer_object(THD* thd, const char *str) :
Json_writer_struct(thd)
{
if (my_writer)
if (unlikely(my_writer))
my_writer->add_member(str).start_object();
}
Json_writer_object::~Json_writer_object()
{
if (!closed && my_writer)
if (my_writer && !closed)
my_writer->end_object();
closed= TRUE;
}
@ -251,20 +284,20 @@ Json_writer_object::~Json_writer_object()
Json_writer_array::Json_writer_array(THD *thd) :
Json_writer_struct(thd)
{
if (my_writer)
if (unlikely(my_writer))
my_writer->start_array();
}
Json_writer_array::Json_writer_array(THD *thd, const char *str) :
Json_writer_struct(thd)
{
if (my_writer)
if (unlikely(my_writer))
my_writer->add_member(str).start_array();
}
Json_writer_array::~Json_writer_array()
{
if (!closed && my_writer)
if (unlikely(my_writer && !closed))
{
my_writer->end_array();
closed= TRUE;
@ -281,7 +314,8 @@ Json_writer_temp_disable::~Json_writer_temp_disable()
thd->opt_trace.enable_tracing_if_required();
}
bool Single_line_formatting_helper::on_add_member(const char *name)
bool Single_line_formatting_helper::on_add_member(const char *name,
size_t len)
{
DBUG_ASSERT(state== INACTIVE || state == DISABLED);
if (state != DISABLED)
@ -290,7 +324,6 @@ bool Single_line_formatting_helper::on_add_member(const char *name)
buf_ptr= buffer;
//append member name to the array
size_t len= strlen(name);
if (len < MAX_LINE_LEN)
{
memcpy(buf_ptr, name, len);
@ -344,12 +377,10 @@ void Single_line_formatting_helper::on_start_object()
bool Single_line_formatting_helper::on_add_str(const char *str,
size_t num_bytes)
size_t len)
{
if (state == IN_ARRAY)
{
size_t len= num_bytes ? num_bytes : strlen(str);
// New length will be:
// "$string",
// quote + quote + comma + space = 4
@ -425,9 +456,11 @@ void Single_line_formatting_helper::disable_and_flush()
while (ptr < buf_ptr)
{
char *str= ptr;
size_t len= strlen(str);
if (nr == 0)
{
owner->add_member(str);
owner->add_member(str, len);
if (start_array)
owner->start_array();
}
@ -435,13 +468,11 @@ void Single_line_formatting_helper::disable_and_flush()
{
//if (nr == 1)
// owner->start_array();
owner->add_str(str);
owner->add_str(str, len);
}
nr++;
while (*ptr!=0)
ptr++;
ptr++;
ptr+= len+1;
}
buf_ptr= buffer;
state= INACTIVE;

View File

@ -86,7 +86,7 @@ public:
void init(Json_writer *owner_arg) { owner= owner_arg; }
bool on_add_member(const char *name);
bool on_add_member(const char *name, size_t len);
bool on_start_array();
bool on_end_array();
@ -184,6 +184,7 @@ class Json_writer
public:
/* Add a member. We must be in an object. */
Json_writer& add_member(const char *name);
Json_writer& add_member(const char *name, size_t len);
/* Add atomic values */
void add_str(const char* val);
@ -202,6 +203,7 @@ public:
private:
void add_unquoted_str(const char* val);
void add_unquoted_str(const char* val, size_t len);
public:
/* Start a child object */
void start_object();
@ -254,63 +256,63 @@ public:
void init(Json_writer *my_writer) { writer= my_writer; }
void add_str(const char* val)
{
if (writer)
if (unlikely(writer))
writer->add_str(val);
}
void add_str(const char* val, size_t length)
{
if (writer)
if (unlikely(writer))
writer->add_str(val, length);
}
void add_str(const String &str)
{
if (writer)
writer->add_str(str);
if (unlikely(writer))
writer->add_str(str.ptr(), str.length());
}
void add_str(LEX_CSTRING str)
void add_str(const LEX_CSTRING &str)
{
if (writer)
writer->add_str(str.str);
if (unlikely(writer))
writer->add_str(str.str, str.length);
}
void add_str(Item *item)
{
if (writer)
if (unlikely(writer))
writer->add_str(item);
}
void add_ll(longlong val)
{
if (writer)
if (unlikely(writer))
writer->add_ll(val);
}
void add_size(longlong val)
{
if (writer)
if (unlikely(writer))
writer->add_size(val);
}
void add_double(double val)
{
if (writer)
if (unlikely(writer))
writer->add_double(val);
}
void add_bool(bool val)
{
if (writer)
if (unlikely(writer))
writer->add_bool(val);
}
void add_null()
{
if (writer)
if (unlikely(writer))
writer->add_null();
}
void add_table_name(const JOIN_TAB *tab)
{
if (writer)
if (unlikely(writer))
writer->add_table_name(tab);
}
void add_table_name(const TABLE* table)
{
if (writer)
if (unlikely(writer))
writer->add_table_name(table);
}
};
@ -333,6 +335,10 @@ public:
context.init(my_writer);
closed= false;
}
bool trace_started()
{
return my_writer != 0;
}
};
@ -349,7 +355,7 @@ class Json_writer_object : public Json_writer_struct
private:
void add_member(const char *name)
{
if (my_writer)
if (unlikely(my_writer))
my_writer->add_member(name);
}
public:
@ -406,11 +412,11 @@ public:
context.add_str(value, num_bytes);
return *this;
}
Json_writer_object& add(const char *name, LEX_CSTRING value)
Json_writer_object& add(const char *name, const LEX_CSTRING &value)
{
DBUG_ASSERT(!closed);
add_member(name);
context.add_str(value.str);
context.add_str(value.str, value.length);
return *this;
}
Json_writer_object& add(const char *name, Item *value)
@ -454,7 +460,7 @@ public:
void end()
{
DBUG_ASSERT(!closed);
if (my_writer)
if (unlikely(my_writer))
my_writer->end_object();
closed= TRUE;
}
@ -478,7 +484,7 @@ public:
void end()
{
DBUG_ASSERT(!closed);
if (my_writer)
if (unlikely(my_writer))
my_writer->end_array();
closed= TRUE;
}
@ -527,10 +533,10 @@ public:
context.add_str(value, num_bytes);
return *this;
}
Json_writer_array& add(LEX_CSTRING value)
Json_writer_array& add(const LEX_CSTRING &value)
{
DBUG_ASSERT(!closed);
context.add_str(value.str);
context.add_str(value.str, value.length);
return *this;
}
Json_writer_array& add(Item *value)

View File

@ -2258,6 +2258,7 @@ public:
void TRP_RANGE::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
DBUG_ASSERT(trace_object->trace_started());
DBUG_ASSERT(param->using_real_indexes);
const uint keynr_in_table= param->real_keynr[key_idx];
@ -2322,6 +2323,7 @@ void TRP_ROR_UNION::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_roworder_union");
Json_writer_array smth_trace(thd, "union_of");
for (TABLE_READ_PLAN **current= first_ror; current != last_ror; current++)
@ -2357,6 +2359,7 @@ void TRP_INDEX_INTERSECT::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_sort_intersect");
Json_writer_array smth_trace(thd, "index_sort_intersect_of");
for (TRP_RANGE **current= range_scans; current != range_scans_end;
@ -2390,6 +2393,7 @@ void TRP_INDEX_MERGE::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_merge");
Json_writer_array smth_trace(thd, "index_merge_of");
for (TRP_RANGE **current= range_scans; current != range_scans_end; current++)
@ -2458,6 +2462,8 @@ void TRP_GROUP_MIN_MAX::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_group").add("index", index_info->name);
if (min_max_arg_part)
@ -5596,6 +5602,8 @@ ha_rows get_table_cardinality_for_index_intersect(TABLE *table)
static
void print_keyparts(THD *thd, KEY *key, uint key_parts)
{
DBUG_ASSERT(thd->trace_started());
KEY_PART_INFO *part= key->key_part;
Json_writer_array keyparts= Json_writer_array(thd, "keyparts");
for(uint i= 0; i < key_parts; i++, part++)
@ -6385,6 +6393,8 @@ void TRP_ROR_INTERSECT::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_roworder_intersect");
trace_object->add("rows", records);
trace_object->add("cost", read_cost);
@ -7424,10 +7434,12 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
{
trace_idx.add("chosen", false);
if (found_records == HA_POS_ERROR)
{
if (key->type == SEL_ARG::Type::MAYBE_KEY)
trace_idx.add("cause", "depends on unread values");
else
trace_idx.add("cause", "unknown");
}
else
trace_idx.add("cause", "cost");
}
@ -15829,6 +15841,7 @@ static void trace_ranges(Json_writer_array *range_trace,
sel_arg_range_seq_next, 0, 0};
KEY *keyinfo= param->table->key_info + param->real_keynr[idx];
uint n_key_parts= param->table->actual_n_key_parts(keyinfo);
DBUG_ASSERT(range_trace->trace_started());
seq.keyno= idx;
seq.real_keyno= param->real_keynr[idx];
seq.param= param;

View File

@ -3050,12 +3050,13 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
}
else
{
Json_writer_object trace(join->thd);
trace.add("strategy", "SJ-Materialization");
/* This is SJ-Materialization with lookups */
Cost_estimate prefix_cost;
signed int first_tab= (int)idx - mat_info->tables;
double prefix_rec_count;
Json_writer_object trace(join->thd);
trace.add("strategy", "SJ-Materialization");
if (first_tab < (int)join->const_tables)
{
prefix_cost.reset();
@ -3084,7 +3085,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
*record_count= prefix_rec_count;
*handled_fanout= new_join_tab->emb_sj_nest->sj_inner_tables;
*strategy= SJ_OPT_MATERIALIZE;
if (unlikely(join->thd->trace_started()))
if (unlikely(trace.trace_started()))
{
trace.add("records", *record_count);
trace.add("read_time", *read_time);
@ -3166,7 +3167,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
*/
*record_count= prefix_rec_count;
*handled_fanout= mat_nest->sj_inner_tables;
if (unlikely(join->thd->trace_started()))
if (unlikely(trace.trace_started()))
{
trace.add("records", *record_count);
trace.add("read_time", *read_time);
@ -3266,7 +3267,7 @@ bool LooseScan_picker::check_qep(JOIN *join,
*/
*strategy= SJ_OPT_LOOSE_SCAN;
*handled_fanout= first->table->emb_sj_nest->sj_inner_tables;
if (unlikely(join->thd->trace_started()))
if (unlikely(trace.trace_started()))
{
trace.add("records", *record_count);
trace.add("read_time", *read_time);
@ -3384,7 +3385,7 @@ bool Firstmatch_picker::check_qep(JOIN *join,
*handled_fanout= firstmatch_need_tables;
/* *record_count and *read_time were set by the above call */
*strategy= SJ_OPT_FIRST_MATCH;
if (unlikely(join->thd->trace_started()))
if (unlikely(trace.trace_started()))
{
trace.add("records", *record_count);
trace.add("read_time", *read_time);
@ -3469,6 +3470,7 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
uint temptable_rec_size;
Json_writer_object trace(join->thd);
trace.add("strategy", "DuplicateWeedout");
if (first_tab == join->const_tables)
{
prefix_rec_count= 1.0;
@ -3529,7 +3531,7 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
*record_count= prefix_rec_count * sj_outer_fanout;
*handled_fanout= dups_removed_fanout;
*strategy= SJ_OPT_DUPS_WEEDOUT;
if (unlikely(join->thd->trace_started()))
if (unlikely(trace.trace_started()))
{
trace.add("records", *record_count);
trace.add("read_time", *read_time);
@ -3727,18 +3729,20 @@ static void recalculate_prefix_record_count(JOIN *join, uint start, uint end)
void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
{
join->sjm_lookup_tables= 0;
join->sjm_scan_tables= 0;
if (!join->select_lex->sj_nests.elements)
return;
THD *thd= join->thd;
uint table_count=join->table_count;
uint tablenr;
table_map remaining_tables= 0;
table_map handled_tabs= 0;
join->sjm_lookup_tables= 0;
join->sjm_scan_tables= 0;
THD *thd= join->thd;
if (!join->select_lex->sj_nests.elements)
return;
Json_writer_object trace_wrapper(thd);
Json_writer_array trace_semijoin_strategies(thd,
"fix_semijoin_strategies_for_picked_join_order");
for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--)
{
POSITION *pos= join->best_positions + tablenr;

View File

@ -105,8 +105,8 @@ void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
Json_writer_object *writer)
{
if (!thd->trace_started())
return;
DBUG_ASSERT(thd->trace_started());
StringBuffer<1024> str(system_charset_info);
ulonglong save_option_bits= thd->variables.option_bits;
thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE;
@ -195,12 +195,11 @@ void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp)
{
if (likely(!(thd->variables.optimizer_trace &
Opt_trace_context::FLAG_ENABLED)) ||
thd->system_thread)
thd->system_thread ||
!thd->trace_started())
return;
Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return;
bool full_access;
Security_context *const backup_thd_sctx= thd->security_context();
thd->set_security_context(&thd->main_security_ctx);
@ -229,13 +228,12 @@ void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp)
void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl)
{
if (likely(!(thd->variables.optimizer_trace &
Opt_trace_context::FLAG_ENABLED)) || thd->system_thread)
Opt_trace_context::FLAG_ENABLED)) ||
thd->system_thread ||
!thd->trace_started())
return;
Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return;
Security_context *const backup_thd_sctx= thd->security_context();
thd->set_security_context(&thd->main_security_ctx);
const TABLE_LIST *const first_not_own_table= thd->lex->first_not_own_table();
@ -290,12 +288,11 @@ void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view,
if (likely(!(thd->variables.optimizer_trace &
Opt_trace_context::FLAG_ENABLED)) ||
thd->system_thread)
return;
Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
thd->system_thread ||
!thd->trace_started())
return;
Opt_trace_context *const trace= &thd->opt_trace;
Security_context *const backup_table_sctx= view->security_ctx;
Security_context *const backup_thd_sctx= thd->security_context();
const GRANT_INFO backup_grant_info= view->grant;
@ -592,6 +589,7 @@ void Opt_trace_stmt::set_allowed_mem_size(size_t mem_size)
void Json_writer::add_table_name(const JOIN_TAB *tab)
{
DBUG_ASSERT(tab->join->thd->trace_started());
if (tab != NULL)
{
char table_name_buffer[SAFE_NAME_LEN];
@ -630,6 +628,7 @@ void Json_writer::add_table_name(const TABLE *table)
void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab)
{
DBUG_ASSERT(thd->trace_started());
Json_writer_object table_records(thd);
table_records.add_table_name(tab);
Json_writer_object table_rec(thd, "table_scan");
@ -655,6 +654,8 @@ void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab)
void trace_plan_prefix(JOIN *join, uint idx, table_map join_tables)
{
THD *const thd= join->thd;
DBUG_ASSERT(thd->trace_started());
Json_writer_array plan_prefix(thd, "plan_prefix");
for (uint i= 0; i < idx; i++)
{
@ -679,6 +680,8 @@ void trace_plan_prefix(JOIN *join, uint idx, table_map join_tables)
void print_final_join_order(JOIN *join)
{
DBUG_ASSERT(join->thd->trace_started());
Json_writer_object join_order(join->thd);
Json_writer_array best_order(join->thd, "best_join_order");
JOIN_TAB *j;
@ -692,6 +695,8 @@ void print_final_join_order(JOIN *join)
void print_best_access_for_table(THD *thd, POSITION *pos,
enum join_type type)
{
DBUG_ASSERT(thd->trace_started());
Json_writer_object trace_best_access(thd, "chosen_access_method");
trace_best_access.add("type", type == JT_ALL ? "scan" :
join_type_str[type]);

View File

@ -2205,11 +2205,6 @@ void THD::reset_globals()
net.thd= 0;
}
bool THD::trace_started()
{
return opt_trace.is_started();
}
/*
Cleanup after query.

View File

@ -3274,7 +3274,10 @@ public:
void reset_for_reuse();
bool store_globals();
void reset_globals();
bool trace_started();
bool trace_started()
{
return opt_trace.is_started();
}
#ifdef SIGNAL_WITH_VIO_CLOSE
inline void set_active_vio(Vio* vio)
{
@ -5003,6 +5006,7 @@ public:
Item *sp_fix_func_item(Item **it_addr);
Item *sp_prepare_func_item(Item **it_addr, uint cols= 1);
bool sp_eval_expr(Field *result_field, Item **expr_item_ptr);
};
/** A short cut for thd->get_stmt_da()->set_ok_status(). */

View File

@ -353,8 +353,10 @@ bool dbug_user_var_equals_int(THD *thd, const char *name, int value)
static void trace_table_dependencies(THD *thd,
JOIN_TAB *join_tabs, uint table_count)
{
DBUG_ASSERT(thd->trace_started());
Json_writer_object trace_wrapper(thd);
Json_writer_array trace_dep(thd, "table_dependencies");
for (uint i= 0; i < table_count; i++)
{
TABLE_LIST *table_ref= join_tabs[i].tab_list;
@ -1469,6 +1471,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
}
}
if (thd->trace_started())
{
Json_writer_object trace_wrapper(thd);
opt_trace_print_expanded_query(thd, select_lex, &trace_wrapper);
@ -5352,6 +5355,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{
Json_writer_object rows_estimation_wrapper(thd);
Json_writer_array rows_estimation(thd, "rows_estimation");
for (s=stat ; s < stat_end ; s++)
{
s->startup_cost= 0;
@ -5496,12 +5500,18 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (select)
delete select;
else
{
if (thd->trace_started())
add_table_scan_values_to_trace(thd, s);
}
}
else
{
if (thd->trace_started())
add_table_scan_values_to_trace(thd, s);
}
}
}
if (pull_out_semijoin_tables(join))
DBUG_RETURN(TRUE);
@ -7402,7 +7412,7 @@ best_access_path(JOIN *join,
Json_writer_object trace_access_idx(thd);
/*
ft-keys require special treatment
full text keys require special treatment
*/
if (ft_key)
{
@ -7414,7 +7424,7 @@ best_access_path(JOIN *join,
records= 1.0;
type= JT_FT;
trace_access_idx.add("access_type", join_type_str[type])
.add("index", keyinfo->name);
.add("full-text index", keyinfo->name);
}
else
{
@ -11866,6 +11876,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
i++;
}
if (unlikely(thd->trace_started()))
{
trace_attached_comp.end();
Json_writer_array trace_attached_summary(thd,
"attached_conditions_summary");
@ -11880,6 +11892,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
trace_one_table.add("attached", cond);
}
}
}
DBUG_RETURN(0);
}

View File

@ -658,9 +658,12 @@ Memory allocated by threads: %s\n",
void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array)
{
DBUG_ASSERT(thd->trace_started());
Json_writer_object wrapper(thd);
Json_writer_array trace_key_uses(thd, "ref_optimizer_key_uses");
for(uint i=0; i < keyuse_array->elements; i++)
for (uint i=0; i < keyuse_array->elements; i++)
{
KEYUSE *keyuse= (KEYUSE*)dynamic_array_ptr(keyuse_array, i);
Json_writer_object keyuse_elem(thd);