概述:

  • 算是一种更详细的执行计划吧

示例:

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