加索引后SELECT仍慢,主因是未按查询模式建复合索引、索引顺序不匹配最左前缀、低区分度字段置顶、ORDER BY未优化;内存参数需据数据量合理配置,大表DDL须用在线工具并压测验证。

为什么加了索引,SELECT 还是慢?
不是所有字段都适合建索引,也不是索引越多越好。常见错误是给 WHERE 里出现的每个字段单独建单列索引,结果优化器根本用不上——MySQL 一般一次查询只走一个二级索引(除非是 INDEX MERGE,但触发条件苛刻且性能不稳定)。
真正有效的做法是按查询模式建**复合索引**,顺序必须匹配 WHERE 条件的最左前缀:比如常查 WHERE status = ? AND created_at > ? ORDER BY updated_at DESC,那就建 INDEX(status, created_at, updated_at);把 created_at 放前面反而会让 status 等值过滤失效。
- 区分度低的字段(如
is_deleted TINYINT)不要放复合索引最左位 -
ORDER BY字段如果和WHERE中范围条件(>,BETWEEN)同类型,可放进索引尾部避免文件排序(Using filesort) - 用
EXPLAIN FORMAT=TRADITIONAL看key_len和Extra,确认是否全用了索引、有没有回表
innodb_buffer_pool_size 设多大才不浪费也不卡顿?
这个参数决定 InnoDB 能缓存多少数据和索引页在内存里。设小了,每次查询都刷磁盘;设太大,可能挤占系统其他进程内存,触发 OOM Killer 杀 MySQL 进程。
经验值是物理内存的 50%–75%,但必须结合实际数据量看:用 SELECT (SELECT SUM(data_length + index_length) FROM information_schema.tables WHERE table_schema = 'your_db') / 1024 / 1024 AS mb; 查下库总大小。如果只有 20GB,服务器有 64GB 内存,设 innodb_buffer_pool_size = 32G 就够用,没必要拉到 48G。
- 线上调大后要等 Buffer Pool 预热完成(可通过
SHOW STATUS LIKE 'Innodb_buffer_pool_%'观察pages_data是否稳定上升) - MySQL 5.7+ 支持在线调整,但只能增大,不能缩小;重启生效的修改更稳妥
- 别忽略
innodb_buffer_pool_instances,设为 8–16(需整除buffer_pool_size),减少并发访问时的锁争用
大表 ALTER TABLE 卡住或失败怎么办?
直接对几千万行的表加索引或改字段类型,MySQL 默认会拷贝全表,锁表时间长,还可能因磁盘空间不足中断(临时表需要额外 2 倍空间)。
优先用 ALGORITHM=INPLACE 支持的操作(如加普通索引、加虚拟列),或者上 pt-online-schema-change 工具。但要注意:pt-osc 本身会持续写入触发器,如果原表 QPS 高、主从延迟大,容易拖垮从库。
- 执行前先关掉
autocommit,手动控制事务粒度,避免长事务阻塞 DDL - 避开业务高峰;用
SELECT COUNT(*)验证新旧表数据一致性,别只信工具日志 - MySQL 8.0 的
INSTANT算法仅支持新增列(非空默认值除外)、重命名列,别误以为所有 DDL 都“瞬时”
tmp_table_size 和 max_heap_table_size 怎么配?
这两个值共同限制内存中临时表大小。一旦查询生成的中间结果(如 GROUP BY、DISTINCT、UNION)超限,MySQL 就会把内存临时表转成磁盘 MyISAM 表,性能断崖式下跌。
设太高可能引发内存溢出,设太低又频繁落盘。建议统一设为 64M–256M,且保持两值相等(否则以较小者为准)。观察 Created_tmp_disk_tables 和 Created_tmp_tables 的比值,超过 10% 就该调了。
- 用
SHOW GLOBAL STATUS LIKE 'Created_tmp%';定期检查,配合慢查日志定位具体哪类 SQL 触发磁盘临时表 - 避免在
GROUP BY里写函数(如DATE(created_at)),会导致无法利用索引,被迫建大临时表 - 复杂报表类查询,宁可拆成子查询或用物化视图(如生成汇总表),也别硬扛大临时表
索引设计和内存参数看着简单,但每张表的数据分布、查询频率、更新节奏都不同,没有一劳永逸的配置。上线前一定在从库上用真实流量压测,而不是只看 EXPLAIN 的理想路径。



















