Files
leetcode-go/笔试/微派 Test1/03-单选题1-索引下推.md
T

90 lines
3.2 KiB
Markdown
Raw Normal View History

2026-05-16 14:15:58 +08:00
---
tags: [笔试, 微派, MySQL, 索引, 数据库]
create time: 2026-05-16 14:45
---
# 03 - 单选题 1:索引下推(Index Condition Pushdown)
## 题目
关于 MySQL InnoDB 存储引擎中的**索引下推(Index Condition Pushdown, ICP)**优化,以下说法**正确**的是:
| 选项 | 内容 |
|------|------|
| A | 索引下推可以将条件判断从存储引擎层下推到 CPU 层执行 |
| B | 索引下推适用于 ALL(全表扫描)类型的查询 |
| C | 使用索引下推可以减少存储引擎访问表的次数(回表次数) |
| D | 索引下推在所有情况下都能提升查询性能 |
<details>
<summary>点击查看答案与解析</summary>
### ✅ 正确答案:**C**
---
### 详细解析
#### 什么是索引下推?
在优化器确定了访问数据的读策略(即选择了哪些索引)之后、读取数据之前,如果 WHERE 子句中还有可以利用索引中字段来评估的条件,则把这些条件的评估操作**下推给存储引擎层**执行,这个技术就叫索引下推。
#### 为什么需要索引下推?(问题背景)
```mermaid
flowchart TD
subgraph IC["无 ICP — 传统方式"]
A[二级索引扫描到匹配的行] --> B["回表到聚簇索引获取完整行"]
B --> C["在 Server 层检查剩余条件"]
C --> D{"满足条件?"}
D -->|"否"| E[丢弃该行]
D -->|"是"| F["返回结果"]
end
subgraph IX["有 ICP — 优化后"]
G[二级索引扫描到匹配的行] --> H["在索引层直接检查剩余条件"]
H --> I{"满足条件?"}
I -->|"否"| J["跳过回表"]
I -->|"是"| K["回表到聚簇索引"]
K --> L["Server 层再确认"]
L --> M["返回结果"]
end
IC -.->|节省回表| IX
```
**没有 ICP 时**:
1. 二级索引只过滤第一个索引列(比如 `name = 'Alice'`)
2. **所有**匹配的行都要**回表**到聚簇索引取完整记录
3. Server 层再检查其他条件(如 `age > 25`)
4. 不满足条件的行被丢弃——但**回表已经发生了**
**有了 ICP 后**:
1. 二级索引不仅过滤第一个列,还**在索引层尝试过滤其余条件**
2. 不满足索引列上的条件的行,**直接跳过回表**
3. 只有同时满足所有索引列条件的行才回表
#### 逐项分析
| 选项 | 正误 | 原因 |
|------|------|------|
| A | ❌ | 反了!ICP 是将条件从**Server 层**(CPU 层)下推到**存储引擎层**。应该是"上推"或题目说反了方向 |
| B | ❌ | ICP 只在**使用二级索引**的查询中生效,ALL(全表扫描)不涉及索引,自然没有 ICP |
| C | ✅ | **正确!**这是 ICP 的核心价值——减少不必要的回表操作 |
| D | ❌ | ICP 需要索引中包含所有用到的列才能发挥效果,而且当回表后的额外过滤代价很低时,收益有限 |
#### 适用场景
```sql
-- 复合索引 (name, age),ICP 可以发挥作用
SELECT * FROM users
WHERE name LIKE 'A%' AND age > 25;
-- 此时二级索引能过滤 name 和 age,减少回表
```
> [!tip] 一句话总结
> 索引下推的本质:把能尽早拒绝的行挡在门外,避免无效的回表开销。
</details>