Mysql如何选择合适的索引

对于我们之前创建的表:employees

假设我们执行如下SQL:
 EXPLAIN select * from employees where name > 'a';

可见上方并未走索引,而当我们执行下方SQL的时候,他走了索引:

 EXPLAIN select * from employees where name > 'zzz';

那么Mysql到底是如何选择索引的呢?我们可以选择trace工具来查看Mysql选择索引的过程。

注意:trace工具开启会影响Mysql性能,使用完毕后需要立即关闭。

trace工具用法:

首先开启trace工具:

set session optimizer_trace="enabled=on",end_markers_in_json=on; 

其次执行查询SQL,下方两条需一起执行:

select * from employees where name > 'a' order by position; 
SELECT * FROM information_schema.OPTIMIZER_TRACE;

将trace列结果拷贝出来,放到文本工具中查看如下:

查看trace字段: 
{
    "steps": [{
            "join_preparation": {‐‐第一阶段: SQL准备阶段, 格式化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最终选择全表扫描

而针对第二条SQL:

select * from employees where name > 'zzz' order by position; 
SELECT * FROM information_schema.OPTIMIZER_TRACE;

{
  "steps": [
    {
      "join_preparation": {
        "select#": 1,
        "steps": [
          {
            "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` > 'zzz') order by `employees`.`position`"
          }
        ] /* steps */
      } /* join_preparation */
    },
    {
      "join_optimization": {
        "select#": 1,
        "steps": [
          {
            "condition_processing": {
              "condition": "WHERE",
              "original_condition": "(`employees`.`name` > 'zzz')",
              "steps": [
                {
                  "transformation": "equality_propagation",
                  "resulting_condition": "(`employees`.`name` > 'zzz')"
                },
                {
                  "transformation": "constant_propagation",
                  "resulting_condition": "(`employees`.`name` > 'zzz')"
                },
                {
                  "transformation": "trivial_condition_removal",
                  "resulting_condition": "(`employees`.`name` > 'zzz')"
                }
              ] /* 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": 100117,
                    "cost": 20378
                  } /* 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": [
                          "zzz < name"
                        ] /* ranges */,
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 1,
                        "cost": 2.21,
                        "chosen": true
                      }
                    ] /* range_scan_alternatives */,
                    "analyzing_roworder_intersect": {
                      "usable": false,
                      "cause": "too_few_roworder_scans"
                    } /* analyzing_roworder_intersect */
                  } /* analyzing_range_alternatives */,
                  "chosen_range_access_summary": {
                    "range_access_plan": {
                      "type": "range_scan",
                      "index": "idx_name_age_position",
                      "rows": 1,
                      "ranges": [
                        "zzz < name"
                      ] /* ranges */
                    } /* range_access_plan */,
                    "rows_for_plan": 1,
                    "cost_for_plan": 2.21,
                    "chosen": true
                  } /* chosen_range_access_summary */
                } /* range_analysis */
              }
            ] /* rows_estimation */
          },
          {
            "considered_execution_plans": [
              {
                "plan_prefix": [
                ] /* plan_prefix */,
                "table": "`employees`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "rows_to_scan": 1,
                      "access_type": "range",
                      "range_details": {
                        "used_index": "idx_name_age_position"
                      } /* range_details */,
                      "resulting_rows": 1,
                      "cost": 2.41,
                      "chosen": true,
                      "use_tmp_table": true
                    }
                  ] /* considered_access_paths */
                } /* best_access_path */,
                "condition_filtering_pct": 100,
                "rows_for_plan": 1,
                "cost_for_plan": 2.41,
                "sort_cost": 1,
                "new_cost_for_plan": 3.41,
                "chosen": true
              }
            ] /* considered_execution_plans */
          },
          {
            "attaching_conditions_to_tables": {
              "original_condition": "(`employees`.`name` > 'zzz')",
              "attached_conditions_computation": [
              ] /* attached_conditions_computation */,
              "attached_conditions_summary": [
                {
                  "table": "`employees`",
                  "attached": "(`employees`.`name` > 'zzz')"
                }
              ] /* 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": "idx_name_age_position",
                "plan_changed": false
              } /* index_order_summary */
            } /* reconsidering_access_paths_for_index_ordering */
          },
          {
            "refine_plan": [
              {
                "table": "`employees`",
                "pushed_index_condition": "(`employees`.`name` > 'zzz')",
                "table_condition_attached": null
              }
            ] /* refine_plan */
          }
        ] /* steps */
      } /* join_optimization */
    },
    {
      "join_execution": {
        "select#": 1,
        "steps": [
          {
            "filesort_information": [
              {
                "direction": "asc",
                "table": "`employees`",
                "field": "position"
              }
            ] /* filesort_information */,
            "filesort_priority_queue_optimization": {
              "usable": false,
              "cause": "not applicable (no LIMIT)"
            } /* filesort_priority_queue_optimization */,
            "filesort_execution": [
            ] /* filesort_execution */,
            "filesort_summary": {
              "rows": 0,
              "examined_rows": 0,
              "number_of_tmp_files": 0,
              "sort_buffer_size": 262056,
              "sort_mode": "<sort_key, packed_additional_fields>"
            } /* filesort_summary */
          }
        ] /* steps */
      } /* join_execution */
    }
  ] /* steps */
}

查看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、付费专栏及课程。

余额充值