sql执行计划计算mysql底层会对sql进行查问优化,根据各个计划所产生的cost成本计算最优执行计划,sql的最终执行计划是否走了索引,抑或为什么没有走索引的起因能够用trace工具来剖析。开启trace:
mysql> set session optimizer_trace="enabled=on",end_markers_in_json=on; ‐‐开启tracemysql> select * from user where name > 'a' order by age;mysql> SELECT * FROM information_schema.OPTIMIZER_TRACE;查看trace字段:
6 {7 "steps": [8 {9 "join_preparation": { ‐‐第一阶段:SQL筹备阶段,格式化sql10 "select#": 1,11 "steps": [12 {13 "expanded_query": "/* select#1 */ select `employees`.`id` AS `id`,`employees`.`name` AS `name`,`employees`.`age` AS `age`,`employees`.`position` AS `position`,`employees`.`hire_time` AS `hire_time` from`employees` where (`employees`.`name` > 'a') order by `employees`.`position`"14 }15 ] /* steps */16 } /* join_preparation */17 },18 {19 "join_optimization": { ‐‐第二阶段:SQL优化阶段20 "select#": 1,21 "steps": [22 {23 "condition_processing": { ‐‐条件解决24 "condition": "WHERE",25 "original_condition": "(`employees`.`name` > 'a')",26 "steps": [27 {28 "transformation": "equality_propagation",29 "resulting_condition": "(`employees`.`name` > 'a')"30 },31 {32 "transformation": "constant_propagation",33 "resulting_condition": "(`employees`.`name` > 'a')"34 },35 {36 "transformation": "trivial_condition_removal",37 "resulting_condition": "(`employees`.`name` > 'a')"38 }39 ] /* steps */40 } /* condition_processing */41 },42 {43 "substitute_generated_columns": {44 } /* substitute_generated_columns */45 },46 {47 "table_dependencies": [ ‐‐表依赖详情48 {49 "table": "`employees`",50 "row_may_be_null": false,51 "map_bit": 0,52 "depends_on_map_bits": [53 ] /* depends_on_map_bits */54 }55 ] /* table_dependencies */56 },57 {58 "ref_optimizer_key_uses": [59 ] /* ref_optimizer_key_uses */60 },61 {62 "rows_estimation": [ ‐‐预估表的拜访老本63 {64 "table": "`employees`",65 "range_analysis": {66 "table_scan": { ‐‐全表扫描状况67 "rows": 10123, ‐‐扫描行数68 "cost": 2054.7 ‐‐查问老本69 } /* table_scan */,70 "potential_range_indexes": [ ‐‐查问可能应用的索引71 {72 "index": "PRIMARY", ‐‐主键索引73 "usable": false,74 "cause": "not_applicable"75 },76 {77 "index": "idx_name_age_position", ‐‐辅助索引78 "usable": true,79 "key_parts": [80 "name",81 "age",82 "position",83 "id"84 ] /* key_parts */85 }86 ] /* potential_range_indexes */,87 "setup_range_conditions": [88 ] /* setup_range_conditions */,89 "group_index_range": {90 "chosen": false,91 "cause": "not_group_by_or_distinct"92 } /* group_index_range */,93 "analyzing_range_alternatives": { ‐‐剖析各个索引应用老本94 "range_scan_alternatives": [95 {96 "index": "idx_name_age_position",97 "ranges": [98 "a < name" ‐‐索引应用范畴99 ] /* ranges */,100 "index_dives_for_eq_ranges": true,101 "rowid_ordered": false, ‐‐应用该索引获取的记录是否依照主键排序102 "using_mrr": false,103 "index_only": false, ‐‐是否应用笼罩索引104 "rows": 5061, ‐‐索引扫描行数105 "cost": 6074.2, ‐‐索引应用老本106 "chosen": false, ‐‐是否抉择该索引107 "cause": "cost"108 }109 ] /* range_scan_alternatives */,110 "analyzing_roworder_intersect": {111 "usable": false,112 "cause": "too_few_roworder_scans"113 } /* analyzing_roworder_intersect */114 } /* analyzing_range_alternatives */115 } /* range_analysis */116 }117 ] /* rows_estimation */118 },119 {120 "considered_execution_plans": [121 {122 "plan_prefix": [123 ] /* plan_prefix */,124 "table": "`employees`",125 "best_access_path": { ‐‐最优拜访门路126 "considered_access_paths": [ ‐‐最终抉择的拜访门路127 {128 "rows_to_scan": 10123,129 "access_type": "scan", ‐‐拜访类型:为scan,全表扫描130 "resulting_rows": 10123,131 "cost": 2052.6,132 "chosen": true, ‐‐确定抉择133 "use_tmp_table": true134 }135 ] /* considered_access_paths */136 } /* best_access_path */,137 "condition_filtering_pct": 100,138 "rows_for_plan": 10123,139 "cost_for_plan": 2052.6,140 "sort_cost": 10123,141 "new_cost_for_plan": 12176,142 "chosen": true143 }144 ] /* considered_execution_plans */145 },146 {147 "attaching_conditions_to_tables": {148 "original_condition": "(`employees`.`name` > 'a')",149 "attached_conditions_computation": [150 ] /* attached_conditions_computation */,151 "attached_conditions_summary": [152 {153 "table": "`employees`",154 "attached": "(`employees`.`name` > 'a')"155 }156 ] /* attached_conditions_summary */157 } /* attaching_conditions_to_tables */158 },159 {160 "clause_processing": {161 "clause": "ORDER BY",162 "original_clause": "`employees`.`position`",163 "items": [164 {165 "item": "`employees`.`position`"166 }167 ] /* items */,168 "resulting_clause_is_simple": true,169 "resulting_clause": "`employees`.`position`"170 } /* clause_processing */171 },172 {173 "reconsidering_access_paths_for_index_ordering": {174 "clause": "ORDER BY",175 "steps": [176 ] /* steps */,177 "index_order_summary": {178 "table": "`employees`",179 "index_provides_order": false,180 "order_direction": "undefined",181 "index": "unknown",182 "plan_changed": false183 } /* index_order_summary */184 } /* reconsidering_access_paths_for_index_ordering */185 },186 {187 "refine_plan": [188 {189 "table": "`employees`"190 }191 ] /* refine_plan */192 }193 ] /* steps */194 } /* join_optimization */195 },196 {197 "join_execution": { ‐‐第三阶段:SQL执行阶段198 "select#": 1,199 "steps": [200 ] /* steps */201 } /* join_execution */202 }203 ] /* steps */204 }205206 论断:全表扫描的老本低于索引扫描,所以mysql最终抉择全表扫描207208 mysql> select * from employees where name > 'zzz' order by position;209 mysql> SELECT * FROM information_schema.OPTIMIZER_TRACE;210211 查看trace字段可知索引扫描的老本低于全表扫描,所以mysql最终抉择索引扫描212(↑↑↑援用↑↑↑)
...