宽索引显著增加Buffer Pool内存压力,因其单页键值数量减少、B+树变高变稀疏、页填充率低导致缓存污染和“内存钉子户”,而窄索引体积小、密度高、复用性强,单位内存产出更高。

宽索引会显著增加 innodb_buffer_pool 的内存压力
因为每个索引页(16KB)能存的键值数量,直接由索引列的总长度决定。宽索引字段多、类型宽(比如多个 VARCHAR(255)、TEXT 前缀、DATETIME + ENUM 组合),单个索引条目就更大,导致每页能存的记录数变少。结果就是:同样数据量下,宽索引需要更多页来组织,这些页全都要进 innodb_buffer_pool 才能高效访问。
宽索引让 B+ 树变“高”且“稀疏”,加剧缓存失效
B+ 树非叶子节点只存键和指针,但键越长,单页能放的键就越少,扇出(fan-out)就下降。树高可能从 3 层涨到 4 层——这意味着每次查询平均多一次磁盘 I/O 或缓冲池查找。更麻烦的是,由于页内有效键少,很多页只填了 30%~50%,大量空闲空间被载入缓冲池却几乎不参与查询,变成“缓存污染”。你查 user_id = ?,结果把整页含 status、create_time、source_channel、device_type 的宽索引页都拉进内存,但其中 70% 的键根本用不上。
联合索引顺序不当会让宽索引的无效部分长期驻留缓冲池
比如建了 (a, b, c, d, e) 却只常查 WHERE a = ? AND c = ?,那 b 列就成了“中间断层”。MySQL 无法跳过 b 直接用 c,导致这个索引对这类查询完全失效;但它的页依然在 innodb_buffer_pool 里占着位置,还可能因频繁写入触发页分裂,生成更多碎片页。这些页既不服务查询,又不轻易被淘汰(LRU 算法对“冷但大”的页不够敏感),实际成了缓冲池里的“内存钉子户”。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
窄索引更容易被复用,单位内存产出更高
一个设计良好的窄索引(如 (user_id, status))往往能覆盖多类查询:WHERE user_id = ?、WHERE user_id = ? AND status = ?、ORDER BY user_id, status。它体积小、页密度高、树矮,加载进缓冲池后服务请求的频次远高于宽索引。而宽索引一旦没被精准命中前缀,就基本闲置——你为它分配的每 MB 缓冲池内存,真实利用率可能不到窄索引的 1/5。
真正容易被忽略的是:索引大小不是看 SHOW INDEX 里显示的 Cardinality,而是看 information_schema.INNODB_INDEX_STATS 中的 avg_length 和实际页填充率。线上表跑久了,宽索引产生的碎片页和半空页,比你想象中更顽固地卡在缓冲池里。










