mysql如何在高并发下优化查询_mysql性能调优方法

来源:这里教程网 时间:2026-02-28 20:52:14 作者:

为什么加索引后查询还是慢

加了索引却没提速,常见原因是查询条件没走索引。比如对

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 层面被拖垮。

相关推荐