Skip to content
/ server Public
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion libmysqld/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/opt_hints_parser.cc ../sql/opt_hints_parser.h
../sql/scan_char.h
../sql/opt_hints.cc ../sql/opt_hints.h
../sql/opt_trace_ddl_info.cc ../sql/opt_trace_ddl_info.h
../sql/opt_store_replay_context.cc ../sql/opt_store_replay_context.h
../sql/sql_json_lib.cc ../sql/sql_json_lib.h
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)
Expand Down
213 changes: 213 additions & 0 deletions mysql-test/include/opt_context_schema.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
let $opt_context_schema=
{
"description": "schema corresponding to the optimizer context section of the trace",
"type": "object",
"properties": {
"current_database": {
"type": "string",
"minLength": 1
},
"list_contexts": {
"type": "array",
"uniqueItems": true,
"minItems": 1,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"ddl": {
"type": "string",
"minLength": 1
},
"num_of_records": {
"type": "number"
},
"read_cost_io": {
"type": "number"
},
"read_cost_cpu": {
"type": "number"
},
"indexes": {
"type": "array",
"uniqueItems": true,
"minItems": 1,
"items": {
"type": "object",
"properties": {
"index_name": {
"type": "string",
"minLength": 1
},
"rec_per_key": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"index_name",
"rec_per_key"
]
}
},
"list_ranges": {
"type": "array",
"uniqueItems": true,
"minItems": 1,
"items": {
"type": "object",
"properties": {
"index_name": {
"type": "string",
"minLength": 1
},
"ranges": {
"type": "array",
"items": {
"type": "string"
}
},
"num_rows": {
"type": "number"
},
"cost": {
"type": "object",
"properties": {
"avg_io_cost": {
"type": "number"
},
"cpu_cost": {
"type": "number"
},
"comp_cost": {
"type": "number"
},
"copy_cost": {
"type": "number"
},
"limit_cost": {
"type": "number"
},
"setup_cost": {
"type": "number"
},
"index_cost_io": {
"type": "number"
},
"index_cost_cpu": {
"type": "number"
},
"row_cost_io": {
"type": "number"
},
"row_cost_cpu": {
"type": "number"
}
},
"required": [
"avg_io_cost",
"cpu_cost",
"comp_cost",
"copy_cost",
"limit_cost",
"setup_cost",
"index_cost_io",
"index_cost_cpu",
"row_cost_io",
"row_cost_cpu"
]
},
"max_index_blocks": {
"type": "number"
},
"max_row_blocks": {
"type": "number"
}
},
"required": [
"index_name",
"ranges",
"num_rows",
"cost",
"max_index_blocks",
"max_row_blocks"
]
}
},
"list_index_read_costs": {
"type": "array",
"uniqueItems": false,
"minItems": 1,
"items": {
"type": "object",
"properties": {
"key_number": {
"type": "number"
},
"num_records": {
"type": "number"
},
"eq_ref": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"index_cost_io": {
"type": "number"
},
"index_cost_cpu": {
"type": "number"
},
"row_cost_io": {
"type": "number"
},
"row_cost_cpu": {
"type": "number"
},
"max_index_blocks": {
"type": "number"
},
"max_row_blocks": {
"type": "number"
},
"copy_cost": {
"type": "number"
}
},
"required": [
"key_number",
"num_records",
"eq_ref",
"index_cost_io",
"index_cost_cpu",
"row_cost_io",
"row_cost_cpu",
"max_index_blocks",
"max_row_blocks",
"copy_cost"
]
}
}
},
"required": [
"name",
"ddl",
"num_of_records",
"read_cost_io",
"read_cost_cpu"
]
}
}
},
"required": [
"current_database",
"list_contexts"
]
};

evalp set @opt_context_schema='$opt_context_schema';
50 changes: 50 additions & 0 deletions mysql-test/include/run_query_twice_and_compare_stats.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# Each query is run twice. However, between the runs
# the table is updated by either adding rows or deleting rows etc.
# During the first run of the query, optimizer_context from the trace
# is saved to a variable "saved_opt_context", and the explain output is saved
# into "saved_explain_output".
# Once the table is modified, the saved context is used to rerun the query.
# The execution plan output along with the stats should be one and the same
# during each run of the query.
#
# Parameters:
# $table_name
# $explain_query
# $table_update_query
#
set optimizer_replay_context="";

echo $explain_query;
let $explain_output=`$explain_query`;

set @trace= (select trace from information_schema.optimizer_trace);
set @saved_opt_context=
(select json_pretty(json_extract(
json_extract(@trace, "$**.optimizer_context"),
'$[0]'
)
));
set @saved_opt_context_var_name='saved_opt_context';

#TO-DO: enable it after MDEV-38033 is resolved
#select JSON_SCHEMA_VALID(@opt_context_schema, @saved_opt_context);

evalp set @explain_output='$explain_output';
set @explain_output= (select json_pretty(round_cost(@explain_output)));
select @explain_output;
set @saved_explain_output=@explain_output;

set optimizer_replay_context="";
eval $table_update_query;
let $analyze_stmt=analyze table $table_name;
eval $analyze_stmt;

set optimizer_replay_context=@saved_opt_context_var_name;

let $explain_output=`$explain_query`;
evalp set @explain_output='$explain_output';
set @explain_output= (select json_pretty(round_cost(@explain_output)));
select JSON_EQUALS(@saved_explain_output, @explain_output);

set optimizer_replay_context="";
5 changes: 3 additions & 2 deletions mysql-test/main/mysqld--help.result
Original file line number Diff line number Diff line change
Expand Up @@ -873,8 +873,9 @@ The following specify which files/extra groups are read (specified before remain
plans based on cost and number of retrieved rows eq_ref:
2 - prune also if we find an eq_ref chain
--optimizer-record-context
Controls storing of optmizer context of all the tables
that are referenced in a query
If set, record the query optimizer context (currently
into the Optimizer trace). Recorded context can be later
replayed to reproduce the query optimizer behavior
--optimizer-row-copy-cost=#
Cost of copying a row from the engine or the join cache
to the SQL layer
Expand Down
Loading