使用方式
打开optimizer trace功能 (默认情况下它是关闭的):
SET optimizer_trace=“enabled=on”;
这里输入你自己的查询语句
SELECT …;
从OPTIMIZER_TRACE表中查看上一个查询的优化过程
SELECT * FROM information_schema.OPTIMIZER_TRACE;
可能你还要观察其他语句执行的优化过程,重复上边的第2、3步
…
当你停止查看语句的优化过程时,把optimizer trace功能关闭
SET optimizer_trace=“enabled=off”;
optimizer trace实践
我们可以把optimizer_trace开关打开:
SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=on;
SET optimizer_trace_offset=-30, optimizer_trace_limit=30;
optimizer_trace默认只显示最近一条SQL的执行计划
我们观察到optimizer_trace_limit、optimizer_trace_offset两个变量,默认值分别为1和-1,表示只保留一条执行计划,同时指向最近的一条记录,我将optimizer_trace_limit和optimizer_trace_offset都修改为5,表示保留最近5条记录,显示前5条
select*from test_index where key1 >'key120'and key1 <'key129';
SELECT*FROM information_schema.OPTIMIZER_TRACE;
看下执行计划
{
"steps": [
{
"join_preparation": {
"select#": 1,
"steps": [
{
// 将select * 转换为 select 每个列
"expanded_query": "/* select#1 */ select `test_index`.`id` AS `id`,`test_index`.`key1` AS `key1`,`test_index`.`key2` AS `key2`,`test_index`.`key3` AS `key3`,`test_index`.`key_part1` AS `key_part1`,`test_index`.`key_part2` AS `key_part2`,`test_index`.`key_part3` AS `key_part3`,`test_index`.`common_field` AS `common_field` from `test_index` where ((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))"
}
]
}
},
{
"join_optimization": {
"select#": 1,
"steps": [
{
// 对查询条件进行处理
"condition_processing": {
// 原始的查询条件
"condition": "WHERE",
"original_condition": "((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))",
"steps": [
{
// 等值转换
"transformation": "equality_propagation",
"resulting_condition": "((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))"
},
{
// 常量传递转换
"transformation": "constant_propagation",
"resulting_condition": "((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))"
},
{
// 琐碎的条件 (去除没用的条件)
"transformation": "trivial_condition_removal",
"resulting_condition": "((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))"
}
]
}
},
{
-- 替换虚拟生成列
"substitute_generated_columns": {
}
},
{
"table_dependencies": [
{
"table": "`test_index`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
]
}
]
},
{
"ref_optimizer_key_uses": [
]
},
{
// 预估不同单表访问方法的访问成本
"rows_estimation": [
{
"table": "`test_index`",
"range_analysis": {
// 全表扫描的行数以及成本
"table_scan": {
"rows": 99316,
"cost": 119181
},
"potential_range_indexes": [
{
// 不能使用主键索引
"index": "PRIMARY",
"usable": false,
"cause": "not_applicable"
},
{
// 不能使用idx_key2索引
"index": "idx_key2",
"usable": false,
"cause": "not_applicable"
},
{
// 不能使用idx_key3索引
"index": "idx_key3",
"usable": false,
"cause": "not_applicable"
},
{
// 不能使用idx_key_part索引
"index": "idx_key_part",
"usable": false,
"cause": "not_applicable"
},
{
// 可以使用idx_key1索引
"index": "idx_key1",
"usable": true,
// 二级索引由 二级索引列+主键索引构成
"key_parts": [
"key1",
"id"
]
}
],
"setup_range_conditions": [
],
// 没有group_by或distinct,不选择通过归集索引的方式
"group_index_range": {
"chosen": false,
"cause": "not_group_by_or_distinct"
},
// 分析各种可能使用的索引的成本
"analyzing_range_alternatives": {
// 通过索引range扫描的方案
"range_scan_alternatives": [
{
"index": "idx_key1",
"ranges": [
"key120 < key1 < key129"
],
"index_dives_for_eq_ranges": true, # 是否使用index dive
"rowid_ordered": false, # 使用该索引获取的记录是否按照主键排序
"using_mrr": false, # 是否使用mrr
"index_only": false, # 是否是索引覆盖访问
"rows": 18254, # 使用该索引获取的记录条数
"cost": 21906, # 使用该索引的成本
"chosen": true # 是否选择该索引
}
],
# 分析使用索引合并的成本
"analyzing_roworder_intersect": {
"usable": false,
"cause": "too_few_roworder_scans"
}
},
# 对于上述单表查询最优的访问方法
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "idx_key1",
"rows": 18254,
"ranges": [
"key120 < key1 < key129"
]
},
"rows_for_plan": 18254,
"cost_for_plan": 21906,
"chosen": true
}
}
}
]
},
{
# 分析各种可能的执行计划
#(对多表查询这可能有很多种不同的方案,单表查询的方案上边已经分析过了,直接选取就好)
"considered_execution_plans": [
{
"plan_prefix": [
],
"table": "`test_index`",
"best_access_path": {
"considered_access_paths": [
{
"rows_to_scan": 18254,
"access_type": "range",
"range_details": {
"used_index": "idx_key1"
},
"resulting_rows": 18254,
"cost": 25557,
"chosen": true
}
]
},
"condition_filtering_pct": 100,
"rows_for_plan": 18254,
"cost_for_plan": 25557,
"chosen": true
}
]
},
{
# 尝试给查询添加一些其他的查询条件
"attaching_conditions_to_tables": {
"original_condition": "((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))",
"attached_conditions_computation": [
{
"table": "`test_index`",
# 重新确认索引的使用,原因是low_limit,查询很少的数据
"rechecking_index_usage": {
"recheck_reason": "low_limit",
"limit": 501,
"row_estimate": 18254
}
}
],
"attached_conditions_summary": [
{
"table": "`test_index`",
"attached": "((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))"
}
]
}
},
{
# 再稍稍的改进一下执行计划
"refine_plan": [
{
"table": "`test_index`",
"pushed_index_condition": "((`test_index`.`key1` > 'key120') and (`test_index`.`key1` < 'key129'))",
"table_condition_attached": null
}
]
}
]
}
},
{
"join_execution": {
"select#": 1,
"steps": [
]
}
}
]
}