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

2次阅读

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

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

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

加了索引却没提速,常见原因是查询条件没走索引。比如对 user_name 建了索引,但写成 WHERE LOWER(user_name) = 'alice'mysql 无法使用索引做前缀匹配;又或者用了 LIKE '%abc' 这种左模糊,索引失效。

实操建议:

  • EXPLAIN select ...type 是否为 refrangekey 列是否显示实际使用的索引
  • 联合索引要注意最左前缀原则,(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),并设置合理 maxLifetimeidleTimeout
  • 检查慢查询或长事务:执行 SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5; 找出卡住的事务
  • 避免在事务里做 rpc、文件读写等耗时操作;显式调用 COMMITROLLBACK,别依赖自动提交
  • 监控 Threads_connectedThreads_running,后者持续高于 50–100 就说明有执行积压

count(*) 为什么越来越慢

InnoDB 的 COUNT(*) 不像 MyISAM 那样直接读元数据,而是要扫描索引(哪怕只扫主键),数据量大 + 并发高时会争抢缓冲池和 CPU。

实操建议:

  • 非强一致性场景,改用近似值:查 information_schema.TABLES 中的 TABLE_ROWS(仅 InnoDB 估算,误差可能达 40%)
  • 高频统计需求,用单独计数表,每次增删时用 INSERT ... ON DUPLICATE KEY UPDATE 维护
  • 避免 COUNT(column) 除非真需要排除 NULLCOUNT(*)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_sizemax_heap_table_size 要同步调大,否则 GROUP BY、ORDER BY 容易触发磁盘临时表,性能断崖下跌

真正卡点往往不在 SQL 写法,而在这些底层机制与业务节奏的错配——比如一个本该毫秒响应的接口,因为日志表没分区、又开了 binlog row 格式、还堆着未 purge 的 undo 日志,最终在 IO 层面被拖垮。

text=ZqhQzanResources