mysql无“索引预加载”功能,其本质依赖innodb_buffer_pool_size足够大且经实际访问后数据页驻留内存;设为物理内存50%–75%(如32gb内存设20–24gb),配合innodb_buffer_pool_load_at_startup与定期dump才能实现冷启动热点恢复。

MySQL 的 innodb_buffer_pool_size 设定不对,索引根本不会“预加载”
MySQL 没有“索引预加载”这个独立功能——所谓预加载,本质是靠 innodb_buffer_pool_size 足够大、且数据页被访问过之后自然留在内存里。如果这个值设得太小(比如默认的 128MB),哪怕你执行了全表扫描或强制 SELECT,索引页也很快被挤出缓冲池,下次查询还是走磁盘。
实操建议:
-
innodb_buffer_pool_size应设为物理内存的 50%–75%,但必须留足空间给 OS 和其他进程(例如:32GB 内存服务器,设成 20GB–24GB 是合理起点) - 重启 MySQL 后,缓冲池是空的;真正“热起来”需要真实查询触发,不是配置完就自动载入所有索引
- 用
SHOW ENGINE INNODB STATUS\G查看Buffer pool hit rate,长期低于 99% 就说明命中不足,可能缺内存或查询太散 - 别迷信
LOAD INDEX INTO CACHE:它只对 MyISAM 有效,InnoDB 完全忽略这条命令
用 SELECT 强刷索引进内存?效果有限还伤性能
有人会写 SELECT pk FROM table WHERE 1=1 或遍历主键来“预热”索引。对 InnoDB 来说,这确实能把对应页读进 buffer pool,但代价很高:
- 全表扫描会触发大量随机 I/O(尤其非聚集索引),可能拖慢线上查询
- 如果表有多个二级索引,
SELECT pk只加载聚簇索引页,二级索引页仍不在内存中 - MySQL 8.0+ 支持
innodb_buffer_pool_load_at_startup=ON,配合定期innodb_buffer_pool_dump_now才能实现较靠谱的“冷启动后快速恢复热点” - 更稳妥的做法是:在低峰期用
SELECT+FORCE INDEX显式访问关键二级索引字段,比如SELECT indexed_col FROM t FORCE INDEX (idx_status)
innodb_buffer_pool_dump_pct 和 innodb_buffer_pool_dump_at_shutdown 怎么配才不白 dump
这两个参数控制“关机前保存哪些页到磁盘”,但很多人开了却没效果,原因常出在比例和时机上。
-
innodb_buffer_pool_dump_at_shutdown=ON是基础,但光开它不够;必须同时设innodb_buffer_pool_load_at_startup=ON,否则启动时根本不读 dump 文件 -
innodb_buffer_pool_dump_pct默认是 25,意思是只 dump 最近最热的 25% 页面——如果业务热点集中,25% 够用;如果访问分散,建议提到 50–75 - dump 文件路径由
innodb_buffer_pool_filename控制,默认是ib_buffer_pool,确保 MySQL 进程对该路径有读写权限,否则静默失败 - dump 文件不是压缩的,几十 GB 缓冲池可能生成几百 MB 文件,注意磁盘空间和启动耗时(MySQL 8.0.22+ 支持并行 load,可设
innodb_buffer_pool_load_now=ON手动触发)
为什么加了索引、调大了 buffer pool,QPS 还上不去?
索引和缓存只是瓶颈的一环。常见被忽略的硬限制:
- 单线程 dump/load 会卡住启动过程,
innodb_buffer_pool_load_now触发时也会短暂阻塞 DML,观察SHOW PROCESSLIST是否卡在Buffer pool load - Linux 的
vm.swappiness=1必须设,否则内核可能把 buffer pool 页 swap 出去,导致“明明内存够,却频繁读盘” - InnoDB 行锁升级、间隙锁冲突、自增锁争用等,会让查询卡在等待锁而非等 IO,此时看
SHOW ENGINE INNODB STATUS的TRANSACTIONS部分比查缓存命中率更有用 - buffer pool 分区数(
innodb_buffer_pool_instances)建议按 CPU 核数设(如 8 核设为 8),避免多线程争抢同一 mutex,尤其在高并发写场景下影响明显
真正的瓶颈往往藏在 buffer pool 之外:锁、网络延迟、客户端连接池配置、甚至 DNS 解析超时。别一上来就调内存参数。











