Skip to content

索引与执行计划

InnoDB 表本身由聚集 B+ Tree 组织。主键索引叶子保存完整行,二级索引叶子保存二级键与主键值,因此二级索引查非覆盖列通常需要回表。


聚集与二级索引

主键会出现在所有二级索引中。宽字符串、频繁更新或完全随机的主键会放大索引、缓存和写入成本。没有显式主键时,InnoDB 会选择第一个合适的 Unique Not Null 索引,否则创建内部行标识。


索引形式

类型用途边界
B-tree等值、范围、排序和前缀匹配默认索引结构
Unique强制业务唯一性NULL 与 Collation 影响唯一语义
Fulltext文本词项搜索分词、停用词和语言能力需验证
Spatial空间对象和谓词使用 R-tree 等空间访问结构,需正确 SRID
Prefix长字符串前缀节省空间但降低选择性,不能覆盖完整值
Functional对表达式结果索引表达式必须满足限制,查询表达式需匹配
Invisible优化器默认忽略但继续维护用于测试删除影响,Unique 约束仍生效

复合索引

sql
CREATE INDEX idx_order_tenant_status_time
ON orders (tenant_id, status, created_at DESC);

该索引适合固定租户、状态后按时间倒序读取。复合索引的使用遵循键顺序:前导列缺失、范围条件位置、排序方向和查询返回比例都会影响可用性。

“把选择性最高列放第一位”不是通用规则。列顺序应同时考虑 Equality、Range、Sort、Group、覆盖需求和高频查询组合。


常见访问策略

策略含义
Index Range Scan扫描连续索引范围
Ref / Eq Ref通过等值键定位一行或少量行
Covering Index所需列均在索引中,避免回表
Index Condition Pushdown在存储引擎层利用索引列提前过滤
Index Merge合并多个索引结果,未必优于专用复合索引
Table Scan读取大部分数据时可能比随机索引访问更合理

函数、隐式类型转换、Collation 不匹配和前导通配符可能让谓词无法形成有效 Index Range,但不能把所有未走索引情况都称为“索引失效”。优化器也可能基于成本主动选择全表扫描。


EXPLAIN 与统计信息

sql
EXPLAIN FORMAT=TREE
SELECT id, created_at
FROM orders
WHERE tenant_id = 10 AND status = 'PAID'
ORDER BY created_at DESC
LIMIT 20;

EXPLAIN ANALYZE
SELECT id FROM orders WHERE tenant_id = 10;

EXPLAIN ANALYZE 会真实执行语句,不应对生产写语句随意使用。阅读时比较估算行数与实际行数、循环次数、执行时间、回表量、排序和临时表。

统计信息不准确时可使用 ANALYZE TABLE 更新。Histogram 可补充无索引列的数据分布,但不会替代索引。Hint 适合诊断和应急,不应掩盖 Schema、统计和 SQL 的根本问题。


索引维护

  • 重复索引和前缀包含索引会增加所有写操作成本。
  • 删除索引前可先设为 Invisible,覆盖完整业务周期观察。
  • Online DDL 不等于零锁或零资源消耗,应确认 Algorithm、Lock 和磁盘余量。
  • 大 OFFSET 分页即使使用索引仍需跳过前序记录,持续翻页优先 Keyset Pagination。

参考资料