[MySQL 面试题]-索引 37-40 一个表有多个索引的时候,能否手动选择使用那个索引?

75 阅读3分钟

image.png

37 一个表有多个索引的时候,能否手动选择使用那个索引?

use index : 建议使用指定索引

ignore index:忽略指定索引

force index:强制使用指定索引,不然可能报错

-- 建议使用 idx_name
select * from user use index(idex_name) where name = 'alice' and email = 'alice@example.com';

-- 忽略 idx_name (如它选择性比较差)
select * from user ignore index(idx_name) where name = 'Alice';

-- 强制使用 idx_emaill (即使优化器认为他性能差)
select * from user force index(idx_email) where email = 'alice@example.com';

38 如何查看一个表的索引?

show index from 表名;

字段含义说明
Table表名
Non_unique是否唯一索引(0 表示唯一)
Key_name索引名称
Seq_in_index列在索引中的顺序(1开始)
Column_name索引列名称
Index_type使用的索引类型(如 BTREE)
Cardinality索引基数(唯一值估计)
Comment备注说明

39 是否可以查看 MySQL 索引选择的逻辑?是否使用过  optimizer_trace?

通过 optimizer_trace 可详细查看优化器如何评估和选择索引.

什么是 optimizer_trace?

optimizer_trace 是MySQL提供的一种调试机制,可以记录SQL查询在执行计划生成过程中,优化器所做每一步决策,包括:

  • 如何评估多个索引;
  • 为什么选择某一个索引:
  • 哪些条件可下推;
  • 是否使用了覆盖索引,索引下推等优化。

开启 optimizer_trace 的方法:

-- 开启 trace 记录(仅当前 session 有效)
set session optimizer_trace="enabled=on",end_markers_in_json=on;

-- 执行目标查询
SELECT * FROM customer WHERE username = 'john_doe' OR age = 25;

-- 查看优化器的执行逻辑
select * from information_schema.OPTIMIZER_TRACE;

set session optimizer_trace="enabled=off";

返回示例解析:

  1. 查询准备阶段 Join Preparation

"expanded_query": "select ... where ((username = 'john_doe') or (age = 25))”

  1. 优化器核心决策 Join Optimization

    1. 条件处理(Condition Processing)
"equality_propagation""constant_propagation""trivial_condition_removal"
  • 目的:标准化查询条件

  • 结果:将age = 25转换为等价表达形式

  • 意义:为后续索引选择做准备

    1. 索引可用性分析
"potential_range_indexes": [
  idx_username (usable),
  idx_age (usable),
  idx_username_age (usable),
  idx_composite (usable)
]
  • 筛选标准:索引必须包含查询条件涉及的列

  • 排除索引

    • PRIMARY(无相关列)
    • idx_birth_date等(无查询条件关联)

3、成本评估与策略选择

  1. 全表扫描 vs 索引合并
方案类型行数成本
全表扫描table_scan204.35
索引合并index_merge21.2575
  • 关键指标

    • rows_for_plan: 优化后的预估行数(2 vs 20)
    • cost_for_plan: 优化后的预估成本(1.4575 vs 4.35)

4、最终执行计划确定

  1. 访问路径选择
"best_access_path": {
  "access_type": "range",
  "used_index": "union(idx_username,idx_age)"
}
  • 选择依据

    • 索引合并成本(1.2575) < 全表扫描(4.35)
    • 结果集预估行数(2)远小于全表扫描(20)

40 多个索引时,MySQL 优化器是如何选择使用哪个索引的?

成本估算模型(Cost-Based Optimizer CBO)自动选择最优的索引路径

原则是最小成本优先,它不会“并发”使用多个普通索引。

  1. 主键(唯一索引)匹配
  2. 全值匹配(单值匹配)
  3. 最左前缀匹配
  4. 范围匹配
  5. 索引扫描
  6. 全表扫描