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

View File

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

View File

@ -2258,6 +2258,7 @@ public:
void TRP_RANGE::trace_basic_info(PARAM *param, void TRP_RANGE::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const Json_writer_object *trace_object) const
{ {
DBUG_ASSERT(trace_object->trace_started());
DBUG_ASSERT(param->using_real_indexes); DBUG_ASSERT(param->using_real_indexes);
const uint keynr_in_table= param->real_keynr[key_idx]; 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 Json_writer_object *trace_object) const
{ {
THD *thd= param->thd; THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_roworder_union"); trace_object->add("type", "index_roworder_union");
Json_writer_array smth_trace(thd, "union_of"); Json_writer_array smth_trace(thd, "union_of");
for (TABLE_READ_PLAN **current= first_ror; current != last_ror; current++) 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 Json_writer_object *trace_object) const
{ {
THD *thd= param->thd; THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_sort_intersect"); trace_object->add("type", "index_sort_intersect");
Json_writer_array smth_trace(thd, "index_sort_intersect_of"); Json_writer_array smth_trace(thd, "index_sort_intersect_of");
for (TRP_RANGE **current= range_scans; current != range_scans_end; 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 Json_writer_object *trace_object) const
{ {
THD *thd= param->thd; THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_merge"); trace_object->add("type", "index_merge");
Json_writer_array smth_trace(thd, "index_merge_of"); Json_writer_array smth_trace(thd, "index_merge_of");
for (TRP_RANGE **current= range_scans; current != range_scans_end; current++) 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 Json_writer_object *trace_object) const
{ {
THD *thd= param->thd; THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_group").add("index", index_info->name); trace_object->add("type", "index_group").add("index", index_info->name);
if (min_max_arg_part) if (min_max_arg_part)
@ -2833,7 +2839,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{ {
{ {
Json_writer_array trace_range_summary(thd, Json_writer_array trace_range_summary(thd,
"setup_range_conditions"); "setup_range_conditions");
tree= cond->get_mm_tree(&param, &cond); tree= cond->get_mm_tree(&param, &cond);
} }
if (tree) if (tree)
@ -5596,6 +5602,8 @@ ha_rows get_table_cardinality_for_index_intersect(TABLE *table)
static static
void print_keyparts(THD *thd, KEY *key, uint key_parts) void print_keyparts(THD *thd, KEY *key, uint key_parts)
{ {
DBUG_ASSERT(thd->trace_started());
KEY_PART_INFO *part= key->key_part; KEY_PART_INFO *part= key->key_part;
Json_writer_array keyparts= Json_writer_array(thd, "keyparts"); Json_writer_array keyparts= Json_writer_array(thd, "keyparts");
for(uint i= 0; i < key_parts; i++, part++) 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 Json_writer_object *trace_object) const
{ {
THD *thd= param->thd; THD *thd= param->thd;
DBUG_ASSERT(trace_object->trace_started());
trace_object->add("type", "index_roworder_intersect"); trace_object->add("type", "index_roworder_intersect");
trace_object->add("rows", records); trace_object->add("rows", records);
trace_object->add("cost", read_cost); 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); trace_idx.add("chosen", false);
if (found_records == HA_POS_ERROR) if (found_records == HA_POS_ERROR)
{
if (key->type == SEL_ARG::Type::MAYBE_KEY) if (key->type == SEL_ARG::Type::MAYBE_KEY)
trace_idx.add("cause", "depends on unread values"); trace_idx.add("cause", "depends on unread values");
else else
trace_idx.add("cause", "unknown"); trace_idx.add("cause", "unknown");
}
else else
trace_idx.add("cause", "cost"); 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}; sel_arg_range_seq_next, 0, 0};
KEY *keyinfo= param->table->key_info + param->real_keynr[idx]; KEY *keyinfo= param->table->key_info + param->real_keynr[idx];
uint n_key_parts= param->table->actual_n_key_parts(keyinfo); uint n_key_parts= param->table->actual_n_key_parts(keyinfo);
DBUG_ASSERT(range_trace->trace_started());
seq.keyno= idx; seq.keyno= idx;
seq.real_keyno= param->real_keynr[idx]; seq.real_keyno= param->real_keynr[idx];
seq.param= param; seq.param= param;

View File

@ -3050,12 +3050,13 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
} }
else else
{ {
Json_writer_object trace(join->thd);
trace.add("strategy", "SJ-Materialization");
/* This is SJ-Materialization with lookups */ /* This is SJ-Materialization with lookups */
Cost_estimate prefix_cost; Cost_estimate prefix_cost;
signed int first_tab= (int)idx - mat_info->tables; signed int first_tab= (int)idx - mat_info->tables;
double prefix_rec_count; double prefix_rec_count;
Json_writer_object trace(join->thd);
trace.add("strategy", "SJ-Materialization");
if (first_tab < (int)join->const_tables) if (first_tab < (int)join->const_tables)
{ {
prefix_cost.reset(); prefix_cost.reset();
@ -3084,7 +3085,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
*record_count= prefix_rec_count; *record_count= prefix_rec_count;
*handled_fanout= new_join_tab->emb_sj_nest->sj_inner_tables; *handled_fanout= new_join_tab->emb_sj_nest->sj_inner_tables;
*strategy= SJ_OPT_MATERIALIZE; *strategy= SJ_OPT_MATERIALIZE;
if (unlikely(join->thd->trace_started())) if (unlikely(trace.trace_started()))
{ {
trace.add("records", *record_count); trace.add("records", *record_count);
trace.add("read_time", *read_time); trace.add("read_time", *read_time);
@ -3166,7 +3167,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
*/ */
*record_count= prefix_rec_count; *record_count= prefix_rec_count;
*handled_fanout= mat_nest->sj_inner_tables; *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("records", *record_count);
trace.add("read_time", *read_time); trace.add("read_time", *read_time);
@ -3266,7 +3267,7 @@ bool LooseScan_picker::check_qep(JOIN *join,
*/ */
*strategy= SJ_OPT_LOOSE_SCAN; *strategy= SJ_OPT_LOOSE_SCAN;
*handled_fanout= first->table->emb_sj_nest->sj_inner_tables; *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("records", *record_count);
trace.add("read_time", *read_time); trace.add("read_time", *read_time);
@ -3384,7 +3385,7 @@ bool Firstmatch_picker::check_qep(JOIN *join,
*handled_fanout= firstmatch_need_tables; *handled_fanout= firstmatch_need_tables;
/* *record_count and *read_time were set by the above call */ /* *record_count and *read_time were set by the above call */
*strategy= SJ_OPT_FIRST_MATCH; *strategy= SJ_OPT_FIRST_MATCH;
if (unlikely(join->thd->trace_started())) if (unlikely(trace.trace_started()))
{ {
trace.add("records", *record_count); trace.add("records", *record_count);
trace.add("read_time", *read_time); trace.add("read_time", *read_time);
@ -3469,6 +3470,7 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
uint temptable_rec_size; uint temptable_rec_size;
Json_writer_object trace(join->thd); Json_writer_object trace(join->thd);
trace.add("strategy", "DuplicateWeedout"); trace.add("strategy", "DuplicateWeedout");
if (first_tab == join->const_tables) if (first_tab == join->const_tables)
{ {
prefix_rec_count= 1.0; 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; *record_count= prefix_rec_count * sj_outer_fanout;
*handled_fanout= dups_removed_fanout; *handled_fanout= dups_removed_fanout;
*strategy= SJ_OPT_DUPS_WEEDOUT; *strategy= SJ_OPT_DUPS_WEEDOUT;
if (unlikely(join->thd->trace_started())) if (unlikely(trace.trace_started()))
{ {
trace.add("records", *record_count); trace.add("records", *record_count);
trace.add("read_time", *read_time); 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) 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 table_count=join->table_count;
uint tablenr; uint tablenr;
table_map remaining_tables= 0; table_map remaining_tables= 0;
table_map handled_tabs= 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_object trace_wrapper(thd);
Json_writer_array trace_semijoin_strategies(thd, Json_writer_array trace_semijoin_strategies(thd,
"fix_semijoin_strategies_for_picked_join_order"); "fix_semijoin_strategies_for_picked_join_order");
for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--) for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--)
{ {
POSITION *pos= join->best_positions + 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) Json_writer_object *writer)
{ {
if (!thd->trace_started()) DBUG_ASSERT(thd->trace_started());
return;
StringBuffer<1024> str(system_charset_info); StringBuffer<1024> str(system_charset_info);
ulonglong save_option_bits= thd->variables.option_bits; ulonglong save_option_bits= thd->variables.option_bits;
thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE; 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 & if (likely(!(thd->variables.optimizer_trace &
Opt_trace_context::FLAG_ENABLED)) || Opt_trace_context::FLAG_ENABLED)) ||
thd->system_thread) thd->system_thread ||
!thd->trace_started())
return; return;
Opt_trace_context *const trace= &thd->opt_trace; Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return;
bool full_access; bool full_access;
Security_context *const backup_thd_sctx= thd->security_context(); Security_context *const backup_thd_sctx= thd->security_context();
thd->set_security_context(&thd->main_security_ctx); 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) void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl)
{ {
if (likely(!(thd->variables.optimizer_trace & 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; return;
Opt_trace_context *const trace= &thd->opt_trace; Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return;
Security_context *const backup_thd_sctx= thd->security_context(); Security_context *const backup_thd_sctx= thd->security_context();
thd->set_security_context(&thd->main_security_ctx); thd->set_security_context(&thd->main_security_ctx);
const TABLE_LIST *const first_not_own_table= thd->lex->first_not_own_table(); 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 & if (likely(!(thd->variables.optimizer_trace &
Opt_trace_context::FLAG_ENABLED)) || Opt_trace_context::FLAG_ENABLED)) ||
thd->system_thread) thd->system_thread ||
return; !thd->trace_started())
Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return; return;
Opt_trace_context *const trace= &thd->opt_trace;
Security_context *const backup_table_sctx= view->security_ctx; Security_context *const backup_table_sctx= view->security_ctx;
Security_context *const backup_thd_sctx= thd->security_context(); Security_context *const backup_thd_sctx= thd->security_context();
const GRANT_INFO backup_grant_info= view->grant; 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) void Json_writer::add_table_name(const JOIN_TAB *tab)
{ {
DBUG_ASSERT(tab->join->thd->trace_started());
if (tab != NULL) if (tab != NULL)
{ {
char table_name_buffer[SAFE_NAME_LEN]; 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) void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab)
{ {
DBUG_ASSERT(thd->trace_started());
Json_writer_object table_records(thd); Json_writer_object table_records(thd);
table_records.add_table_name(tab); table_records.add_table_name(tab);
Json_writer_object table_rec(thd, "table_scan"); 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) void trace_plan_prefix(JOIN *join, uint idx, table_map join_tables)
{ {
THD *const thd= join->thd; THD *const thd= join->thd;
DBUG_ASSERT(thd->trace_started());
Json_writer_array plan_prefix(thd, "plan_prefix"); Json_writer_array plan_prefix(thd, "plan_prefix");
for (uint i= 0; i < idx; i++) 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) void print_final_join_order(JOIN *join)
{ {
DBUG_ASSERT(join->thd->trace_started());
Json_writer_object join_order(join->thd); Json_writer_object join_order(join->thd);
Json_writer_array best_order(join->thd, "best_join_order"); Json_writer_array best_order(join->thd, "best_join_order");
JOIN_TAB *j; JOIN_TAB *j;
@ -692,6 +695,8 @@ void print_final_join_order(JOIN *join)
void print_best_access_for_table(THD *thd, POSITION *pos, void print_best_access_for_table(THD *thd, POSITION *pos,
enum join_type type) enum join_type type)
{ {
DBUG_ASSERT(thd->trace_started());
Json_writer_object trace_best_access(thd, "chosen_access_method"); Json_writer_object trace_best_access(thd, "chosen_access_method");
trace_best_access.add("type", type == JT_ALL ? "scan" : trace_best_access.add("type", type == JT_ALL ? "scan" :
join_type_str[type]); join_type_str[type]);

View File

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

View File

@ -3274,7 +3274,10 @@ public:
void reset_for_reuse(); void reset_for_reuse();
bool store_globals(); bool store_globals();
void reset_globals(); void reset_globals();
bool trace_started(); bool trace_started()
{
return opt_trace.is_started();
}
#ifdef SIGNAL_WITH_VIO_CLOSE #ifdef SIGNAL_WITH_VIO_CLOSE
inline void set_active_vio(Vio* vio) inline void set_active_vio(Vio* vio)
{ {
@ -5003,6 +5006,7 @@ public:
Item *sp_fix_func_item(Item **it_addr); Item *sp_fix_func_item(Item **it_addr);
Item *sp_prepare_func_item(Item **it_addr, uint cols= 1); Item *sp_prepare_func_item(Item **it_addr, uint cols= 1);
bool sp_eval_expr(Field *result_field, Item **expr_item_ptr); bool sp_eval_expr(Field *result_field, Item **expr_item_ptr);
}; };
/** A short cut for thd->get_stmt_da()->set_ok_status(). */ /** 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, static void trace_table_dependencies(THD *thd,
JOIN_TAB *join_tabs, uint table_count) JOIN_TAB *join_tabs, uint table_count)
{ {
DBUG_ASSERT(thd->trace_started());
Json_writer_object trace_wrapper(thd); Json_writer_object trace_wrapper(thd);
Json_writer_array trace_dep(thd, "table_dependencies"); Json_writer_array trace_dep(thd, "table_dependencies");
for (uint i= 0; i < table_count; i++) for (uint i= 0; i < table_count; i++)
{ {
TABLE_LIST *table_ref= join_tabs[i].tab_list; 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); Json_writer_object trace_wrapper(thd);
opt_trace_print_expanded_query(thd, select_lex, &trace_wrapper); 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_object rows_estimation_wrapper(thd);
Json_writer_array rows_estimation(thd, "rows_estimation"); Json_writer_array rows_estimation(thd, "rows_estimation");
for (s=stat ; s < stat_end ; s++) for (s=stat ; s < stat_end ; s++)
{ {
s->startup_cost= 0; s->startup_cost= 0;
@ -5496,10 +5500,16 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (select) if (select)
delete select; delete select;
else else
add_table_scan_values_to_trace(thd, s); {
if (thd->trace_started())
add_table_scan_values_to_trace(thd, s);
}
} }
else else
add_table_scan_values_to_trace(thd, s); {
if (thd->trace_started())
add_table_scan_values_to_trace(thd, s);
}
} }
} }
@ -7402,7 +7412,7 @@ best_access_path(JOIN *join,
Json_writer_object trace_access_idx(thd); Json_writer_object trace_access_idx(thd);
/* /*
ft-keys require special treatment full text keys require special treatment
*/ */
if (ft_key) if (ft_key)
{ {
@ -7414,7 +7424,7 @@ best_access_path(JOIN *join,
records= 1.0; records= 1.0;
type= JT_FT; type= JT_FT;
trace_access_idx.add("access_type", join_type_str[type]) trace_access_idx.add("access_type", join_type_str[type])
.add("index", keyinfo->name); .add("full-text index", keyinfo->name);
} }
else else
{ {
@ -11866,18 +11876,21 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
i++; i++;
} }
trace_attached_comp.end(); if (unlikely(thd->trace_started()))
Json_writer_array trace_attached_summary(thd,
"attached_conditions_summary");
for (tab= first_depth_first_tab(join); tab;
tab= next_depth_first_tab(join, tab))
{ {
if (!tab->table) trace_attached_comp.end();
continue; Json_writer_array trace_attached_summary(thd,
Item *const cond = tab->select_cond; "attached_conditions_summary");
Json_writer_object trace_one_table(thd); for (tab= first_depth_first_tab(join); tab;
trace_one_table.add_table_name(tab); tab= next_depth_first_tab(join, tab))
trace_one_table.add("attached", cond); {
if (!tab->table)
continue;
Item *const cond = tab->select_cond;
Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(tab);
trace_one_table.add("attached", cond);
}
} }
} }
DBUG_RETURN(0); 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) void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array)
{ {
DBUG_ASSERT(thd->trace_started());
Json_writer_object wrapper(thd); Json_writer_object wrapper(thd);
Json_writer_array trace_key_uses(thd, "ref_optimizer_key_uses"); 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); KEYUSE *keyuse= (KEYUSE*)dynamic_array_ptr(keyuse_array, i);
Json_writer_object keyuse_elem(thd); Json_writer_object keyuse_elem(thd);