使用方式
打开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": []}}]}
