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";
返回示例解析:
- 查询准备阶段 Join Preparation
"expanded_query": "select ... where ((username = 'john_doe') or (age = 25))”
-
优化器核心决策 Join Optimization
- 条件处理(Condition Processing)
"equality_propagation" → "constant_propagation" → "trivial_condition_removal"
-
目的:标准化查询条件
-
结果:将
age = 25转换为等价表达形式 -
意义:为后续索引选择做准备
- 索引可用性分析
"potential_range_indexes": [
idx_username (usable),
idx_age (usable),
idx_username_age (usable),
idx_composite (usable)
]
-
筛选标准:索引必须包含查询条件涉及的列
-
排除索引:
- PRIMARY(无相关列)
- idx_birth_date等(无查询条件关联)
3、成本评估与策略选择
- 全表扫描 vs 索引合并
| 方案 | 类型 | 行数 | 成本 |
|---|---|---|---|
| 全表扫描 | table_scan | 20 | 4.35 |
| 索引合并 | index_merge | 2 | 1.2575 |
-
关键指标:
rows_for_plan: 优化后的预估行数(2 vs 20)cost_for_plan: 优化后的预估成本(1.4575 vs 4.35)
4、最终执行计划确定
- 访问路径选择
"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)自动选择最优的索引路径
原则是最小成本优先,它不会“并发”使用多个普通索引。
- 主键(唯一索引)匹配
- 全值匹配(单值匹配)
- 最左前缀匹配
- 范围匹配
- 索引扫描
- 全表扫描