mysql索引优化之trace使用

34 篇文章 0 订阅
9 篇文章 0 订阅

我们在用explain查看sql语句进行优化时会发现一个问题。
在有索引的情况下。有时候mysql会走索引,有时候又不走索引,这到底是为什么呢?
为了弄清楚这个玄学问题,下面介绍一个工具。trace
破除玄学迷信,从我做起!
trace:这是一个可以将mysql内部执行器的步骤及逻辑以json的形式返回。
mysql内部在执行sql语句之前会先大概算一下走索引和全表扫描之间的性能消耗。两者会算出一个数值。该数值只适用于该条sql语句。数值越小,性能消耗越小,执行器就会选择消耗小的那一个。而有时候执行器走索引的数值不一定比不走索引的数值小。
所以:我们根据json中执行器执行全表扫描,和索引扫描之间所消耗的数值大小即可知道为什么mysql为什么有时候走索引,有时候不走索引。
下面开始介绍用法。
mysql最 终如何选择索引,我们可以用trace工具来一查究竟,开启trace工具会影响mysql性能,所以只能临时分析sql使用,用 完之后立即关闭 trace工具用法:

set session optimizer_trace="enabled=on",end_markers_in_json=on; ‐‐开启traceset session optimizer_trace="enabled=on",end_markers_in_json=on; ‐‐开启trace
 select * from employees where name > 'a' order by position; 3  SELECT * FROM information_schema.OPTIMIZER_TRACE;
查看trace字段: 
 {
   "steps": [ 
    {  "join_preparation": { ‐‐第一阶段:SQL准备阶段 
     "select#": 1, 
      "steps": [ 
       { 
        "expanded_query": "/* select#1 */ select `employees`.`id` AS `id`,`employees`.`name` AS `name`,`empl oyees`.`age` AS `age`,`employees`.`position` AS `position`,`employees`.`hire_time` AS `hire_time` from `employees` where (`employees`.`name` > 'a') order by `employees`.`position`" 
         } 
          ] /* steps */ 
           } /* join_preparation */
 }, 
  { 
   "join_optimization": { ‐‐第二阶段:SQL优化阶段 
    "select#": 1, 
     "steps": [ 
      {
       "condition_processing": { ‐‐条件处理 
        "condition": "WHERE", 
         "original_condition": "(`employees`.`name` > 'a')", 
          "steps": [ 
           { 
            "transformation": "equality_propagation", 
             "resulting_condition": "(`employees`.`name` > 'a')" 
              }, 
               { 
                "transformation": "constant_propagation", 
                 "resulting_condition": "(`employees`.`name` > 'a')" 
                  }, 
                   { 
                    "transformation": "trivial_condition_removal", 
                     "resulting_condition": "(`employees`.`name` > 'a')" 
                      } 
                       ] /* steps */ 
                        } /* condition_processing */ 
                         }, 
                          { 
                           "substitute_generated_columns": { 
                            } /* substitute_generated_columns */ 
                             }, 
                              { 
                               "table_dependencies": [ ‐‐表依赖详情 
                                { 
                                 "table": "`employees`", 
                                  "row_may_be_null": false, 
                                   "map_bit": 0, 
                                    "depends_on_map_bits": [ 
                                     ] /* depends_on_map_bits */ 
                                      } 
                                       ] /* table_dependencies */ 
                                        }, 
                                         {  "ref_optimizer_key_uses": [ 
                                          ] /* ref_optimizer_key_uses */ 
                                           },
                                         {  "rows_estimation": [ ‐‐预估表的访问成本 
                                          {  "table": "`employees`", "range_analysis": {  "table_scan": { ‐‐全表扫描情况 
                                           "rows": 10123, ‐‐扫描行数 
                                            "cost": 2054.7 ‐‐查询成本 
                                             } /* table_scan */,
 "potential_range_indexes": [ ‐‐查询可能使用的索引 
  { 
   "index": "PRIMARY", ‐‐主键索引 
    "usable": false, 
     "cause": "not_applicable" 
      }, 
       { 
        "index": "idx_name_age_position", ‐‐辅助索引 
         "usable": true, 
          "key_parts": [ 
           "name", 
            "age", 
             "position", 
              "id" 
              
               ] /* key_parts */ 
                } 
                 ] /* potential_range_indexes */, 
                  "setup_range_conditions": [ 
                   ] /* setup_range_conditions */, 
                    "group_index_range": { 
                     "chosen": false, 
                      "cause": "not_group_by_or_distinct" 
                       } /* group_index_range */, 
                        "analyzing_range_alternatives": { ‐‐分析各个索引使用成本 
                         "range_scan_alternatives": [ 
                          { 
                           "index": "idx_name_age_position", 
                            "ranges": [ 
                             "a < name" ‐‐索引使用范围 
                              ] /* ranges */, 
                               "index_dives_for_eq_ranges": true, 
                                "rowid_ordered": false, ‐‐使用该索引获取的记录是否按照主键排序 
                                 "using_mrr": false, 
                                  "index_only": false, ‐‐是否使用覆盖索引 
                                   "rows": 5061, ‐‐索引扫描行数 
                                    "cost": 6074.2, ‐‐索引使用成本 
                                     "chosen": false, ‐‐是否选择该索引 
                                      "cause": "cost" 
                                       }  ] /* range_scan_alternatives */,  "analyzing_roworder_intersect": { 
                                        "usable": false,  "cause": "too_few_roworder_scans" 
                                         } /* analyzing_roworder_intersect */ 
                                          } /* analyzing_range_alternatives */ 
                                           } /* range_analysis */ 
                                            }  ] /* rows_estimation */  },  { "considered_execution_plans": [ {
 "plan_prefix": [  ] /* plan_prefix */,  "table": "`employees`", 
  "best_access_path": { ‐‐最优访问路径 
  "considered_access_paths": [ ‐‐最终选择的访问路径 
   {  "rows_to_scan": 10123,  "access_type": "scan", ‐‐访问类型:为scan,全表扫描 
    "resulting_rows": 10123,  "cost": 2052.6,  "chosen": true, ‐‐确定选择  "use_tmp_table": true  }  ] /* considered_access_paths */  } /* best_access_path */,  "condition_filtering_pct": 100,  "rows_for_plan": 10123,  "cost_for_plan": 2052.6, "sort_cost": 10123,  "new_cost_for_plan": 12176, "chosen": true  } ] /* considered_execution_plans */ }, {  "attaching_conditions_to_tables": {  "original_condition": "(`employees`.`name` > 'a')", "attached_conditions_computation": [  ] /* attached_conditions_computation */,  "attached_conditions_summary": [ { "table": "`employees`","attached": "(`employees`.`name` > 'a')"  } ] /* attached_conditions_summary */} /* attaching_conditions_to_tables */  },  { "clause_processing": {  "clause": "ORDER BY",  "original_clause": "`employees`.`position`",  "items": [  { "item": "`employees`.`position`" } ] /* items */,  "resulting_clause_is_simple": true,  "resulting_clause": "`employees`.`position`" } /* clause_processing */  },  { "reconsidering_access_paths_for_index_ordering": {  "clause": "ORDER BY",
 "steps": [ ] /* steps */,  "index_order_summary": {  "table": "`employees`", "index_provides_order": false,  "order_direction": "undefined",  "index": "unknown",  "plan_changed": false  } /* index_order_summary */ } /* reconsidering_access_paths_for_index_ordering */  }, { "refine_plan": [  {  "table": "`employees`" }  ] /* refine_plan */ } ] /* steps */  } /* join_optimization */  }, {  "join_execution": { ‐‐第三阶段:SQL执行阶段 
  "select#": 1,  "steps": [  ] /* steps */ } /* join_execution */  }  ] /* steps */  }  

结论:全表扫描的成本低于索引扫描,所以mysql最终选择全表扫描
select * from employees where name > ‘zzz’ order by position;
SELECT * FROM information_schema.OPTIMIZER_TRACE;
查看trace字段可知索引扫描的成本低于全表扫描,所以mysql最终选择索引扫描
set session optimizer_trace=“enabled=off”; ‐‐关闭trace

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值