MySQL InnoDB 索引:B+树、聚簇索引与执行计划
解释 InnoDB 聚簇索引和二级索引的关系,纠正索引结构中的常见混淆,并用可复现查询说明如何阅读执行计划。
理解索引的关键不是记住某个固定树高,而是理解查询条件、索引顺序与需要读取的数据之间的关系。
先明确讨论对象
本文聚焦 MySQL InnoDB 的常见 B+树索引。其他存储引擎或不同索引类型可能有不同实现,不能把所有 MySQL 索引都描述成同一种数据结构。
索引让数据库有机会通过有组织的数据结构缩小访问范围,但它需要空间,并增加写入维护成本。是否建立索引,应由查询条件、数据分布和写入负载共同决定。
聚簇索引与二级索引
InnoDB 的聚簇索引叶子记录保存行数据。通常使用主键作为聚簇索引;没有显式主键时,InnoDB 会按规则选择合适的唯一非空索引,或生成隐藏的聚簇索引。因此,“表必须由开发者声明主键才能存储数据”并不准确,虽然显式设计主键通常更便于维护。
二级索引记录包含其索引列及主键值。一次查询若还需要二级索引无法提供的列,可能需要继续访问聚簇索引;如果所需数据已被索引覆盖,则可以减少额外访问。
原文将“非聚集索引”直接等同于 MyISAM,忽略了 InnoDB 同样存在二级索引,本次已纠正。
为什么不能用固定树高推导性能
原记录使用页大小、键长度和行长度估算一棵树可存储多少数据。估算可以帮助理解扇出,但这些数字属于模型假设,不是所有表的固定值。记录开销、页利用率、索引类型及数据分布都会影响实际结构。
也不应把通用 B 树的节点大小直接说成固定 16 KB,或把每次节点访问都等价成一次物理磁盘 I/O。实际访问可能由缓存满足。
同样,“达到亿级必须分库分表”不能作为单一判断规则。应先测量查询与写入瓶颈,再考虑索引、查询改写、归档或架构调整。
用一个查询建立分析路径
以下仅供隔离的实验数据库使用,未在用户原库执行。
CREATE TABLE demo_article_index (
id BIGINT PRIMARY KEY,
author_id BIGINT NOT NULL,
published_at DATETIME NOT NULL,
title VARCHAR(200) NOT NULL
);
EXPLAIN
SELECT id, published_at
FROM demo_article_index
WHERE author_id = 10
ORDER BY published_at DESC
LIMIT 20;
CREATE INDEX idx_author_published
ON demo_article_index(author_id, published_at);
EXPLAIN
SELECT id, published_at
FROM demo_article_index
WHERE author_id = 10
ORDER BY published_at DESC
LIMIT 20;
实验前需要插入具有代表性的数据。只有空表或几条记录时,执行计划和耗时不具备推广价值。比较时记录访问类型、使用的索引、估计扫描行数以及排序相关信息。
EXPLAIN 的行数通常是估计值,不能当作实际读取量。版本支持时可进一步使用运行时分析工具,但执行前要理解它会不会真正运行 SQL。
主键设计的取舍
较短、稳定的主键有利于控制索引开销;顺序递增键在某些写入模式下便于维护。但不能把字符串主键概括为“转换成 ASCII 后破坏索引”。字符比较由类型和排序规则决定,具体代价应通过实际工作负载判断。
文章值得展示的结论应是“这一条 SQL 在这组数据上为什么改善”,而不是“有索引一定更快”。
参考
- 本文标签: Java Mysql
- 本文链接: https://www.tianyajuanke.top/article/34
- 版权声明: 本文由吴沛芙原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权