加索引后查询仍慢的主因是索引未覆盖、顺序不当或隐式类型转换致失效;高并发下卡顿多由锁争用、元数据锁等待或主从延迟引发。
为什么加索引后查询还是慢?
高并发下即使有索引,SELECT 仍可能卡住,常见原因是索引未覆盖查询字段、索引列顺序不合理,或存在隐式类型转换导致索引失效。比如 WHERE user_id = '123'(user_id 是 INT),MySQL 会强制转为数字再比对,但某些版本下会放弃使用索引。
实操建议:
- 用
EXPLAIN FORMAT=TREE查看执行计划,确认是否走了预期索引,尤其注意filtered值是否远低于 100(说明实际扫描行数远超预估) - 联合索引要遵循「最左前缀」,且把高频过滤、区分度高的列放前面;排序字段若在
ORDER BY中出现,尽量包含在索引末尾(避免Using filesort) - 避免在索引列上做函数操作,如
WHERE DATE(create_time) = '2024-01-01'→ 改成WHERE create_time >= '2024-01-01' AND create_time
连接池配置不当会直接拖垮QPS
应用层连接池(如 HikariCP、Druid)若最大连接数设得过高,MySQL 的 max_connections 很快被耗尽,新请求排队等待,表现为连接超时或 Too many connections 错误;设得太低又会造成线程饥饿,吞吐上不去。
实操建议:
- 先查 MySQL 实际峰值连接数:
SHOW STATUS LIKE 'Threads_connected';,结合监控观察 95 分位值,max_connections建议设为该值的 1.5–2 倍 - HikariCP 中
maximumPoolSize不宜超过 20–30(除非 IO 密集型且数据库硬件极强),并开启connection-timeout(推荐 3000ms)防止阻塞扩散 - 务必关闭自动提交(
autoCommit=false),显式控制事务边界,避免长事务占用连接
读写分离没生效?可能是事务里混了写操作
很多业务以为只要用了主从架构,查询就会自动走从库——其实不然。一旦当前连接处于事务中(哪怕只执行了一条 SELECT),后续所有语句(包括读)都会路由到主库,否则无法保证一致性。