MySQL 索引

最后更新: 2022-06-16 20:46:43 +0800 +0800
原文以英文撰写。您正在阅读AI翻译版本。

InnoDB 使用 B+ 树实现主索引和二级索引。当索引顺序符合选择性谓词、连接、范围扫描或排序要求时,它可以减少 I/O;但每个被索引的行都会增加写入工作和存储开销。

聚簇索引和二级索引 #

InnoDB 表将行数据存储在其聚簇索引中。InnoDB 会选择声明的主键;否则会选择第一个合适的非空唯一键,或者创建内部隐藏键。应声明简短且稳定的主键,因为每个二级索引条目都会存储主键值。

二级索引存储其索引列和主键值。需要二级索引中不存在的列的查询,会为每个匹配条目执行一次聚簇索引查找。只有在经过测量的成本确实可以消除时,才添加覆盖索引;更宽的索引会降低页面扇出并增加写入开销。

复合索引 #

对于 (tenant_id, created_at, id),B+ 树可以高效定位:

sql
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 树页面缓存为内部优化。前缀索引可以减少长文本键的字节数,但前提是所选前缀仍具有选择性。

sql
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 仍继续维护该索引:

sql
ALTER TABLE event ALTER INDEX event_tenant_created INVISIBLE;
ALTER TABLE event ALTER INDEX event_tenant_created VISIBLE;

在检查代表性查询和约束要求之前,不要删除索引。每个额外索引都会消耗页面,并增加插入、删除、更新、重做日志、缓冲池、备份和复制工作。因此,索引选择必须在经过测量的读取收益、写放大和运维成本之间取得平衡。

参考资料 #

评论

在 GitHub 上阅读或评论(发表评论需要登录)