更详细的执行计划 optimizer_trace

本文介绍了如何在MySQL中进行数据准备,包括创建表`t2`和插入数据。接着展示了如何开启optimizer_trace来查看SQL执行的优化过程。在示例中,对查询`select * from t2 where a<10 and b<100 and 1=1;`进行了分析,解释了条件处理、索引使用和执行计划的选择,特别是选择了使用`a`索引而非`b`索引的原因,因为其成本更低。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

数据准备

查看 optimizer_trace


数据准备

CREATE TABLE `t2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11),
  `b` int(11),
  `c` varchar(16) ,
  `create_time` datetime,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

插入数据
for(int i=1; i< 10000; i++) {
    insert into t2(id, a, b, c, create_time) values(i, i, i%/1000, 'qweqwe', now())
}

查看 optimizer_trace

/* 打开optimizer_trace,只对本线程有效 */

SET optimizer_trace='enabled=on'; (set 后面加 global 则对所以线程有效)

执行sql select * from t2 where a < 10 and b < 100 and 1 = 1;

 /* 查看 OPTIMIZER_TRACE 输出 */

SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G;

输出内容如下

*************************** 1. row ***************************
QUERY: select * from t2 where a < 10 and b < 100 and 1 = 1   ### 执行的 sql 语句
TRACE: {
  "steps": [
    {
      "join_preparation": {      ### perpare 阶段
        "select#": 1,
        "steps": [
          {
            "expanded_query": "/* select#1 */ select `t2`.`id` AS `id`,`t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c`,`t2`.`create_time` AS `create_time` from `t2` where ((`t2`.`a` < 10) and (`t2`.`b` < 100) and (1 = 1))"
          }
        ]
      }
    },
    {
      "join_optimization": {   ### optimize 阶段
        "select#": 1,
        "steps": [
          {
            "condition_processing": {  ### 处理搜索条件
              "condition": "WHERE",
              "original_condition": "((`t2`.`a` < 10) and (`t2`.`b` < 100) and (1 = 1))",  ### 原始搜索条件
              "steps": [
                {
                  "transformation": "equality_propagation",  ### 等值判断处理
                  "resulting_condition": "((`t2`.`a` < 10) and (`t2`.`b` < 100) and (1 = 1))"
                },
                {
                  "transformation": "constant_propagation",  ### 等值传递替换
                  "resulting_condition": "((`t2`.`a` < 10) and (`t2`.`b` < 100) and (1 = 1))"
                },
                {
                  "transformation": "trivial_condition_removal", ### 去除无用条件,这里将 1 = 1 去掉了
                  "resulting_condition": "((`t2`.`a` < 10) and (`t2`.`b` < 100))"
                }
              ]
            }
          },
          {
            "substitute_generated_columns": {  ### 替换虚拟生成列
            }
          },
          {
            "table_dependencies": [  ### 表依赖信息
              {
                "table": "`t2`",
                "row_may_be_null": false,
                "map_bit": 0,
                "depends_on_map_bits": [
                ]
              }
            ]
          },
          {
            "ref_optimizer_key_uses": [
            ]
          },
          {
            "rows_estimation": [ ### 预估不用单表访问方式的访问成本
              {
                "table": "`t2`",
                "range_analysis": {
                  "table_scan": {  ### 全表访问方式
                    "rows": 9932,
                    "cost": 2085.5
                  },
                  "potential_range_indexes": [  ### 分析可能使用的索引
                    {
                      "index": "PRIMARY",
                      "usable": false,
                      "cause": "not_applicable"  ### applicable 的中文意思是,可适用的;可应用的;合适的
                    },
                    {
                      "index": "a",
                      "usable": true,
                      "key_parts": [
                        "a",
                        "id"
                      ]
                    },
                    {
                      "index": "b",
                      "usable": true,
                      "key_parts": [
                        "b",
                        "id"
                      ]
                    }
                  ],
                  "setup_range_conditions": [
                  ],
                  "group_index_range": {
                    "chosen": false,
                    "cause": "not_group_by_or_distinct"considered_execution_plans
                  },
                  "analyzing_range_alternatives": { ### 分析各种可能使用的索引的成本
                    "range_scan_alternatives": [
                      {
                        "index": "a",   ### 使用 a 索引
                        "ranges": [
                          "NULL < a < 10"
                        ],
                        "index_dives_for_eq_ranges": true, ### 计算查询成本 使用 index dive 的方式
                        "rowid_ordered": false, ### 使用该索引获取的记录是否按照主键排序
                        "using_mrr": false,     ### 是否使用 mrr 算法
                        "index_only": false,    ### 是否使用覆盖索引,fasle:没使用
                        "rows": 9,              ### 扫描行数
                        "cost": 11.81,          ### 查询成本
                        "chosen": true          ### 是否被执行计划选中,true 选中
                      },
                      {
                        "index": "b",
                        "ranges": [
                          "NULL < b < 100"
                        ],
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 1000,
                        "cost": 1201,
                        "chosen": false,
                        "cause": "cost"     ### 因为成本太大而不选择该索引
                      }
                    ],
                    "analyzing_roworder_intersect": {  ### 分析索引合并的成本
                      "usable": false,
                      "cause": "too_few_roworder_scans"
                    }
                  },
                  "chosen_range_access_summary": {  ### 对于该 sql 最优的访问方法
                    "range_access_plan": {
                      "type": "range_scan",
                      "index": "a",
                      "rows": 9,
                      "ranges": [
                        "NULL < a < 10"
                      ]
                    },
                    "rows_for_plan": 9,
                    "cost_for_plan": 11.81,
                    "chosen": true
                  }
                }
              }
            ]
          },
          {
            "considered_execution_plans": [  ###?? 分析各种可能的执行计划(对于多表查询,可能有很多种不同的方案)
              {
                "plan_prefix": [
                ],
                "table": "`t2`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "rows_to_scan": 9,
                      "access_type": "range",
                      "range_details": {
                        "used_index": "a"
                      },
                      "resulting_rows": 9,
                      "cost": 13.61,
                      "chosen": true
                    }
                  ]
                },
                "condition_filtering_pct": 100,
                "rows_for_plan": 9,
                "cost_for_plan": 13.61,
                "chosen": true
              }
            ]
          },
          {
            "attaching_conditions_to_tables": { ### ?? 尝试给查询添加一些其他的查询条件
              "original_condition": "((`t2`.`a` < 10) and (`t2`.`b` < 100))",
              "attached_conditions_computation": [
              ],
              "attached_conditions_summary": [
                {
                  "table": "`t2`",
                  "attached": "((`t2`.`a` < 10) and (`t2`.`b` < 100))"
                }
              ]
            }
          },
          {
            "refine_plan": [ ### 在稍微改进下执行计划
              {
                "table": "`t2`",
                "pushed_index_condition": "(`t2`.`a` < 10)",
                "table_condition_attached": "(`t2`.`b` < 100)"
              }
            ]
          }
        ]
      }
    },
    {
      "join_execution": { ### execute阶段
        "select#": 1,
        "steps": [
        ]
      }
    }
  ]
}
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
INSUFFICIENT_PRIVILEGES: 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值