如果想打开这个功能,必须首先把enabled的值改为on

优化过程大致分为了三个阶段:

  • prepare阶段
  • optimize阶段
  • execute阶段 ```sql SET optimizer_trace=”enabled=on”;

SELECT * FROM s1 WHERE key1 > ‘z’ AND key2 < 1000000 AND key3 IN (‘a’, ‘b’, ‘c’) AND common_field = ‘abc’;

SELECT * FROM information_schema.OPTIMIZER_TRACE\G

* 1. row *

分析的查询语句是什么

QUERY: SELECT * FROM s1 WHERE key1 > ‘z’ AND key2 < 1000000 AND key3 IN (‘a’, ‘b’, ‘c’) AND common_field = ‘abc’

优化的具体过程

TRACE: { “steps”: [ { “join_preparation”: { # prepare阶段 “select#”: 1, “steps”: [ { “IN_uses_bisection”: true }, { “expanded_query”: “/ select#1 / select s1.id AS id,s1.key1 AS key1,s1.key2 AS key2,s1.key3 AS key3,s1.key_part1 AS key_part1,s1.key_part2 AS key_part2,s1.key_part3 AS key_part3,s1.common_field AS common_field from s1 where ((s1.key1 > ‘z’) and (s1.key2 < 1000000) and (s1.key3 in (‘a’,’b’,’c’)) and (s1.common_field = ‘abc’))” } ] / steps / } / join_preparation / }, { “join_optimization”: { # optimize阶段 “select#”: 1, “steps”: [ { “condition_processing”: { # 处理搜索条件 “condition”: “WHERE”,

  1. # 原始搜索条件
  2. "original_condition": "((`s1`.`key1` > 'z') and (`s1`.`key2` < 1000000) and (`s1`.`key3` in ('a','b','c')) and (`s1`.`common_field` = 'abc'))",
  3. "steps": [
  4. {
  5. # 等值传递转换
  6. "transformation": "equality_propagation",
  7. "resulting_condition": "((`s1`.`key1` > 'z') and (`s1`.`key2` < 1000000) and (`s1`.`key3` in ('a','b','c')) and (`s1`.`common_field` = 'abc'))"
  8. },
  9. {
  10. # 常量传递转换
  11. "transformation": "constant_propagation",
  12. "resulting_condition": "((`s1`.`key1` > 'z') and (`s1`.`key2` < 1000000) and (`s1`.`key3` in ('a','b','c')) and (`s1`.`common_field` = 'abc'))"
  13. },
  14. {
  15. # 去除没用的条件
  16. "transformation": "trivial_condition_removal",
  17. "resulting_condition": "((`s1`.`key1` > 'z') and (`s1`.`key2` < 1000000) and (`s1`.`key3` in ('a','b','c')) and (`s1`.`common_field` = 'abc'))"
  18. }
  19. ] /* steps */
  20. } /* condition_processing */
  21. },
  22. {
  23. # 替换虚拟生成列
  24. "substitute_generated_columns": {
  25. } /* substitute_generated_columns */
  26. },
  27. {
  28. # 表的依赖信息
  29. "table_dependencies": [
  30. {
  31. "table": "`s1`",
  32. "row_may_be_null": false,
  33. "map_bit": 0,
  34. "depends_on_map_bits": [
  35. ] /* depends_on_map_bits */
  36. }
  37. ] /* table_dependencies */
  38. },
  39. {
  40. "ref_optimizer_key_uses": [
  41. ] /* ref_optimizer_key_uses */
  42. },
  43. {
  44. # 预估不同单表访问方法的访问成本
  45. "rows_estimation": [
  46. {
  47. "table": "`s1`",
  48. "range_analysis": {
  49. "table_scan": { # 全表扫描的行数以及成本
  50. "rows": 9688,
  51. "cost": 2036.7
  52. } /* table_scan */,
  53. # 分析可能使用的索引
  54. "potential_range_indexes": [
  55. {
  56. "index": "PRIMARY", # 主键不可用
  57. "usable": false,
  58. "cause": "not_applicable"
  59. },
  60. {
  61. "index": "idx_key2", # idx_key2可能被使用
  62. "usable": true,
  63. "key_parts": [
  64. "key2"
  65. ] /* key_parts */
  66. },
  67. {
  68. "index": "idx_key1", # idx_key1可能被使用
  69. "usable": true,
  70. "key_parts": [
  71. "key1",
  72. "id"
  73. ] /* key_parts */
  74. },
  75. {
  76. "index": "idx_key3", # idx_key3可能被使用
  77. "usable": true,
  78. "key_parts": [
  79. "key3",
  80. "id"
  81. ] /* key_parts */
  82. },
  83. {
  84. "index": "idx_key_part", # idx_keypart不可用
  85. "usable": false,
  86. "cause": "not_applicable"
  87. }
  88. ] /* potential_range_indexes */,
  89. "setup_range_conditions": [
  90. ] /* setup_range_conditions */,
  91. "group_index_range": {
  92. "chosen": false,
  93. "cause": "not_group_by_or_distinct"
  94. } /* group_index_range */,
  95. # 分析各种可能使用的索引的成本
  96. "analyzing_range_alternatives": {
  97. "range_scan_alternatives": [
  98. {
  99. # 使用idx_key2的成本分析
  100. "index": "idx_key2",
  101. # 使用idx_key2的范围区间
  102. "ranges": [
  103. "NULL < key2 < 1000000"
  104. ] /* ranges */,
  105. "index_dives_for_eq_ranges": true, # 是否使用index dive
  106. "rowid_ordered": false, # 使用该索引获取的记录是否按照主键排序
  107. "using_mrr": false, # 是否使用mrr
  108. "index_only": false, # 是否是索引覆盖访问
  109. "rows": 12, # 使用该索引获取的记录条数
  110. "cost": 15.41, # 使用该索引的成本
  111. "chosen": true # 是否选择该索引
  112. },
  113. {
  114. # 使用idx_key1的成本分析
  115. "index": "idx_key1",
  116. # 使用idx_key1的范围区间
  117. "ranges": [
  118. "z < key1"
  119. ] /* ranges */,
  120. "index_dives_for_eq_ranges": true, # 同上
  121. "rowid_ordered": false, # 同上
  122. "using_mrr": false, # 同上
  123. "index_only": false, # 同上
  124. "rows": 266, # 同上
  125. "cost": 320.21, # 同上
  126. "chosen": false, # 同上
  127. "cause": "cost" # 因为成本太大所以不选择该索引
  128. },
  129. {
  130. # 使用idx_key3的成本分析
  131. "index": "idx_key3",
  132. # 使用idx_key3的范围区间
  133. "ranges": [
  134. "a <= key3 <= a",
  135. "b <= key3 <= b",
  136. "c <= key3 <= c"
  137. ] /* ranges */,
  138. "index_dives_for_eq_ranges": true, # 同上
  139. "rowid_ordered": false, # 同上
  140. "using_mrr": false, # 同上
  141. "index_only": false, # 同上
  142. "rows": 21, # 同上
  143. "cost": 28.21, # 同上
  144. "chosen": false, # 同上
  145. "cause": "cost" # 同上
  146. }
  147. ] /* range_scan_alternatives */,
  148. # 分析使用索引合并的成本
  149. "analyzing_roworder_intersect": {
  150. "usable": false,
  151. "cause": "too_few_roworder_scans"
  152. } /* analyzing_roworder_intersect */
  153. } /* analyzing_range_alternatives */,
  154. # 对于上述单表查询s1最优的访问方法
  155. "chosen_range_access_summary": {
  156. "range_access_plan": {
  157. "type": "range_scan",
  158. "index": "idx_key2",
  159. "rows": 12,
  160. "ranges": [
  161. "NULL < key2 < 1000000"
  162. ] /* ranges */
  163. } /* range_access_plan */,
  164. "rows_for_plan": 12,
  165. "cost_for_plan": 15.41,
  166. "chosen": true
  167. } /* chosen_range_access_summary */
  168. } /* range_analysis */
  169. }
  170. ] /* rows_estimation */
  171. },
  172. {
  173. # 分析各种可能的执行计划
  174. #(对多表查询这可能有很多种不同的方案,单表查询的方案上边已经分析过了,直接选取idx_key2就好)
  175. "considered_execution_plans": [
  176. {
  177. "plan_prefix": [
  178. ] /* plan_prefix */,
  179. "table": "`s1`",
  180. "best_access_path": {
  181. "considered_access_paths": [
  182. {
  183. "rows_to_scan": 12,
  184. "access_type": "range",
  185. "range_details": {
  186. "used_index": "idx_key2"
  187. } /* range_details */,
  188. "resulting_rows": 12,
  189. "cost": 17.81,
  190. "chosen": true
  191. }
  192. ] /* considered_access_paths */
  193. } /* best_access_path */,
  194. "condition_filtering_pct": 100,
  195. "rows_for_plan": 12,
  196. "cost_for_plan": 17.81,
  197. "chosen": true
  198. }
  199. ] /* considered_execution_plans */
  200. },
  201. {
  202. # 尝试给查询添加一些其他的查询条件
  203. "attaching_conditions_to_tables": {
  204. "original_condition": "((`s1`.`key1` > 'z') and (`s1`.`key2` < 1000000) and (`s1`.`key3` in ('a','b','c')) and (`s1`.`common_field` = 'abc'))",
  205. "attached_conditions_computation": [
  206. ] /* attached_conditions_computation */,
  207. "attached_conditions_summary": [
  208. {
  209. "table": "`s1`",
  210. "attached": "((`s1`.`key1` > 'z') and (`s1`.`key2` < 1000000) and (`s1`.`key3` in ('a','b','c')) and (`s1`.`common_field` = 'abc'))"
  211. }
  212. ] /* attached_conditions_summary */
  213. } /* attaching_conditions_to_tables */
  214. },
  215. {
  216. # 再稍稍的改进一下执行计划
  217. "refine_plan": [
  218. {
  219. "table": "`s1`",
  220. "pushed_index_condition": "(`s1`.`key2` < 1000000)",
  221. "table_condition_attached": "((`s1`.`key1` > 'z') and (`s1`.`key3` in ('a','b','c')) and (`s1`.`common_field` = 'abc'))"
  222. }
  223. ] /* refine_plan */
  224. }
  225. ] /* steps */
  226. } /* join_optimization */
  227. },
  228. {
  229. "join_execution": { # execute阶段
  230. "select#": 1,
  231. "steps": [
  232. ] /* steps */
  233. } /* join_execution */
  234. }

] / steps / }

因优化过程文本太多而丢弃的文本字节大小,值为0时表示并没有丢弃

MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0

权限字段

INSUFFICIENT_PRIVILEGES: 0

1 row in set (0.00 sec) ```