索引与失效

返回 MySQL

理论推导见 索引;执行计划见 EXPLAIN

B+ 树(InnoDB)

  • 数据在叶子节点,叶子双向链表支持范围扫描
  • 非叶子只存键,扇出高、树矮

索引类型

类型说明
聚簇索引(主键)叶节点 = 完整行
二级索引叶节点 = 索引列 + 主键,可能回表
唯一索引允许多个 NULL
联合索引最左前缀
覆盖索引Extra: Using index

最左前缀

索引 (a, b, c)

条件使用
a = ?✅ a
a = ? AND b = ?✅ a, b
a = ? AND c = ?⚠️ 仅 a
b = ?
a > ? AND b = ?⚠️ a 范围后 b 常失效

设计:等值列在前,范围/排序在后,如 (user_id, created_at)


索引失效(重点)

1. 对索引列使用函数

-- ❌
WHERE YEAR(created_at) = 2024
-- ✅
WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01'

8.0+ 生成列索引:

ALTER TABLE t ADD COLUMN created_year INT AS (YEAR(created_at)) STORED,
  ADD INDEX idx_year (created_year);

2. 隐式类型转换

-- phone VARCHAR,传入数字 → 索引失效
WHERE phone = 13800138000
-- ✅
WHERE phone = '13800138000'

3. LIKE

WHERE name LIKE 'Alice%'   -- ✅ 前缀
WHERE name LIKE '%Alice'   -- ❌

大文本用 FULLTEXTElasticsearch

4. OR / NOT

-- ✅ 拆 UNION
SELECT * FROM t WHERE id = 1
UNION ALL
SELECT * FROM t WHERE name = 'x' AND id <> 1;

5. ORDER BY / GROUP BY

-- 索引 (user_id, created_at)
WHERE user_id = 1 ORDER BY created_at;  -- ✅
WHERE user_id IN (1,2,3) ORDER BY created_at;  -- ⚠️ 常 filesort

6. 优化器选全表扫

选择性太低、统计过期 → ANALYZE TABLE orders;

7. 字符集不一致

JOIN/WHERE 两侧 collation 不同 → 可能 CONVERT。统一 utf8mb4_unicode_ci

自查清单

检查动作
EXPLAIN.key 为 NULLtyperows
Using filesort / temporary调索引或 SQL
函数包列改范围或生成列
隐式转换SHOW WARNINGS

相关