加索引后查询仍慢的主因是查询条件未走索引,如函数操作、左模糊匹配、违反最左前缀原则、隐式类型转换或低区分度字段建索引;应通过explain验证索引使用情况。

为什么加索引后查询还是慢
加了索引却没提速,常见原因是查询条件没走索引。比如对 user_name 建了索引,但写成 WHERE LOWER(user_name) = 'alice',MySQL 无法使用索引做前缀匹配;又或者用了 LIKE '%abc' 这种左模糊,索引失效。
实操建议:
- 用
EXPLAIN SELECT ...看type是否为ref或range,key列是否显示实际使用的索引 - 联合索引要注意最左前缀原则,
(a,b,c)索引能加速WHERE a=1 AND b=2,但对WHERE b=2无效 - 避免在索引列上做函数操作、类型隐式转换(如字符串字段跟数字比较)
- 区分度低的字段(如
status TINYINT只有 0/1)单独建索引意义不大,可考虑覆盖索引或组合优化
高并发下连接数打满怎么办
现象是应用报错 Too many connections,或 SHOW PROCESSLIST 里大量 Sleep 状态连接堆积。根本原因常是应用层未正确复用连接,或事务长期不提交。
实操建议:
- 调大
max_connections是临时解法,更关键的是控制客户端行为:确认应用是否启用了连接池(如 HikariCP),并设置合理maxLifetime和idleTimeout - 检查慢查询或长事务:执行
SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5;找出卡住的事务 - 避免在事务里做 RPC、文件读写等耗时操作;显式调用
COMMIT或ROLLBACK,别依赖自动提交 - 监控
Threads_connected和Threads_running,后者持续高于 50–100 就说明有执行积压
count(*) 为什么越来越慢
InnoDB 的 COUNT(*) 不像 MyISAM 那样直接读元数据,而是要扫描索引(哪怕只扫主键),数据量大 + 并发高时会争抢缓冲池和 CPU。
实操建议:
- 非强一致性场景,改用近似值:查
information_schema.TABLES中的TABLE_ROWS(仅 InnoDB 估算,误差可能达 40%) - 高频统计需求,用单独计数表,每次增删时用
INSERT ... ON DUPLICATE KEY UPDATE维护 - 避免
COUNT(column)除非真需要排除 NULL;COUNT(*)和COUNT(1)在 MySQL 8.0+ 性能一致,不用纠结写法 - 如果必须精确且高频,考虑把聚合逻辑前置到写入链路(如用 Kafka + Flink 实时更新 Redis 计数)
哪些配置项最容易被忽略但影响巨大
很多调优只盯着 innodb_buffer_pool_size,但几个小参数在高并发下反而更敏感。
实操建议:
-
innodb_log_file_size太小会导致频繁 checkpoint,增大到 1–2GB(配合innodb_log_files_in_group=2)可显著降低刷盘压力 -
innodb_flush_log_at_trx_commit=2比默认值 1 更抗压(牺牲极小概率的秒级事务丢失),适合日志类、消息类业务 -
query_cache_type=0(MySQL 8.0 已移除,但 5.7 还有)必须关,开启后高并发下锁竞争严重 -
tmp_table_size和max_heap_table_size要同步调大,否则 GROUP BY、ORDER BY 容易触发磁盘临时表,性能断崖下跌
真正卡点往往不在 SQL 写法,而在这些底层机制与业务节奏的错配——比如一个本该毫秒响应的接口,因为日志表没分区、又开了 binlog row 格式、还堆着未 purge 的 undo 日志,最终在 IO 层面被拖垮。











