InnoDB 使用 B+ 树实现主索引和二级索引。当索引顺序符合选择性谓词、连接、范围扫描或排序要求时,它可以减少 I/O;但每个被索引的行都会增加写入工作和存储开销。
聚簇索引和二级索引 #
InnoDB 表将行数据存储在其聚簇索引中。InnoDB 会选择声明的主键;否则会选择第一个合适的非空唯一键,或者创建内部隐藏键。应声明简短且稳定的主键,因为每个二级索引条目都会存储主键值。
二级索引存储其索引列和主键值。需要二级索引中不存在的列的查询,会为每个匹配条目执行一次聚簇索引查找。只有在经过测量的成本确实可以消除时,才添加覆盖索引;更宽的索引会降低页面扇出并增加写入开销。
复合索引 #
对于 (tenant_id, created_at, id),B+ 树可以高效定位:
WHERE tenant_id = ? AND created_at >= ?
ORDER BY created_at, id仅从 created_at 开始无法高效查找,因为树的顺序从 tenant_id 开始。在常见设计中,等值谓词位于范围谓词之前,随后是满足排序或覆盖所需的列。使用 EXPLAIN ANALYZE 验证选择;索引顺序取决于实际谓词、数据分布和结果大小。
索引类型和诊断 #
UNIQUE 在创建访问路径的同时强制执行不变量。大多数 InnoDB 索引都是 B 树。
FULLTEXT 索引支持基于词元的文本搜索,SPATIAL 索引对几何值使用 R 树。
MySQL 还介绍了 MEMORY 引擎的哈希索引;InnoDB 不会公开通用哈希索引,尽管其自适应哈希索引可以将频繁访问的 B 树页面缓存为内部优化。前缀索引可以减少长文本键的字节数,但前提是所选前缀仍具有选择性。
EXPLAIN ANALYZE
SELECT id, created_at
FROM event
WHERE tenant_id = 7
AND created_at >= '2026-01-01'
ORDER BY created_at, id
LIMIT 100;应检查实际行数、循环次数和耗时,而不是假设索引会被使用。统计信息、基数估计和较小的结果集都可能使全表扫描比索引遍历更便宜。
SHOW INDEX 报告的是估算基数,而不是精确的不同值数量。在有充分理由时,使用
ANALYZE TABLE 刷新过时的统计信息,然后用 EXPLAIN ANALYZE 的测量结果比较优化器估计值。不可见索引允许管理员像索引不存在一样测试执行计划,同时 InnoDB 仍继续维护该索引:
ALTER TABLE event ALTER INDEX event_tenant_created INVISIBLE;
ALTER TABLE event ALTER INDEX event_tenant_created VISIBLE;在检查代表性查询和约束要求之前,不要删除索引。每个额外索引都会消耗页面,并增加插入、删除、更新、重做日志、缓冲池、备份和复制工作。因此,索引选择必须在经过测量的读取收益、写放大和运维成本之间取得平衡。
评论
在 GitHub 上阅读或评论(发表评论需要登录)