### MySQL 最左前缀匹配原则
**最左前缀匹配原则** 是 MySQL 使用联合索引时的一个重要优化规则。它指的是在查询条件中,只有符合索引最左侧字段开始的连续前缀部分时,索引才能被有效利用。
#### 1. 最左前缀匹配的含义
- **联合索引**:一个索引包含多个列,例如 `CREATE INDEX idx_col ON table (a, b, c);`。
- **最左前缀**:指联合索引中从最左侧开始连续的一个或多个列。只有查询条件使用了从最左侧开始的列,或者符合从最左侧列开始的部分连续列时,索引才会生效。
#### 2. 示例分析
假设有一张表 `users`,表结构如下:
```sql
CREATE TABLE users (
id INT PRIMARY KEY,
a INT,
b INT,
c INT,
KEY idx_abc (a, b, c)
);
```
不同查询条件的索引使用情况如下:
| **查询条件** | **最左前缀匹配** | **是否使用索引** |
| --- | --- | --- |
| `WHERE a = 1` | 匹配 `a` | 是 |
| `WHERE a = 1 AND b = 2` | 匹配 `a, b` | 是 |
| `WHERE a = 1 AND b = 2 AND c = 3` | 匹配 `a, b, c` | 是 |
| `WHERE b = 2` | 不匹配(未从最左列开始) | 否 |
| `WHERE c = 3` | 不匹配(未从最左列开始) | 否 |
| `WHERE b = 2 AND c = 3` | 不匹配(跳过了 a) | 否 |
#### 3. 索引前缀的灵活性
##### 3.1 范围查询对索引的影响
- 范围条件(如 `<`, `>`, `BETWEEN`, `LIKE` 等)会中断最左前缀匹配后续列的索引使用。
- 示例:
```sql
SELECT * FROM users WHERE a = 1 AND b > 2 AND c = 3;
```
- **分析**:
- `a = 1` 和 `b > 2` 满足索引 `a, b` 的最左前缀匹配。
- 但由于 `b > 2` 是范围查询,`c = 3` 无法继续利用索引。
##### 3.2 `LIKE` 模式匹配
- 如果 `LIKE` 以通配符(如 `%`)开头,会破坏索引匹配。
- 示例:
```sql
SELECT * FROM users WHERE a LIKE '%1';
```
- **分析**:
- 由于 `LIKE` 以 `%` 开头,索引 `a` 无法被利用。
#### 4. 查询优化器的作用
- **查询优化器**:MySQL 的查询优化器会自动调整 `WHERE` 子句的条件顺序,以使用适合的索引。因此,SQL 语句中字段的顺序不需要和联合索引定义的字段顺序相同,查询优化器会判断并生成最高效的执行计划。
#### 5. 实际应用
- **设计联合索引时**:应充分考虑查询条件的需求,将经常作为查询条件的列放在联合索引的最左侧,这样可以最大限度地利用索引的优势。
- **案例**:假设我们有一个用户表 `users`,经常需要根据用户名 `username` 和年龄 `age` 进行查询。那么,我们可以考虑创建一个联合索引 `(username, age)`,而不是 `(age, username)`。这样,当我们根据用户名查询时,索引可以得到充分利用。
```sql
CREATE INDEX idx_username_age ON users (username, age);
```
### 总结
最左前缀匹配原则是 MySQL 使用联合索引时的重要优化规则。通过确保查询条件从索引的最左侧开始匹配,MySQL 可以快速定位到所需数据,从而减少磁盘 I/O 操作,提升查询性能。设计联合索引时,应将经常作为查询条件的列放在最左侧,以充分利用索引的优势。