MySQL 8.1.0并行执行SELECT全表查询为何未达预期性能?
为什么并行执行全表扫描查询无法达到预期性能?
核心结论
MySQL支持多连接并行处理查询,但这类全表扫描场景受限于缓存竞争、结果传输开销、线程模型等瓶颈,无法实现线性性能提升(比如8核就快8倍)。
1. InnoDB缓冲池的全局竞争
你的查询是全表扫描,依赖InnoDB缓冲池的缓存数据。虽然缓冲池足够大,但它是全局共享资源:
- 多个线程同时扫描聚簇索引(
employees的主键是聚簇索引)时,会竞争缓存页的latch(轻量级锁),导致线程等待,无法真正并行执行。 - 多线程同时访问缓存会降低CPU缓存命中率,原本单线程能高效利用CPU缓存,多线程下缓存失效增多,反而增加内存访问耗时。
2. 结果集传输的累加开销
每个查询要返回30万条数据,即便数据在内存中,以下开销是无法避免的:
- MySQL需要将内存中的数据序列化后发送给客户端,这个过程有CPU开销,多个连接同时处理时会占用大量CPU资源。
- 本地回环网络也有内核态传输开销,8个连接同时发送大量数据时,会出现带宽饱和(即使是localhost,内核也需要处理数据包)。
- PHP的
reap_async_query接收结果时,也需要将数据从内核态拷贝到用户态,这部分开销会累加。
3. 线程模型与系统调度限制
- MySQL默认采用单连接单线程模型,8个连接会启动8个工作线程,但系统中还有MySQL后台线程(比如缓冲池刷新、日志写入线程)占用CPU,导致查询线程无法完全占满8个核心。
- Windows系统的线程调度效率远低于Linux,线程切换开销更大,这也是你在Windows上性能更差的原因。
4. 单查询的CPU占比不高
单查询耗时140ms,其中大部分时间不是CPU计算,而是数据遍历和结果传输。当并行执行时,CPU不是瓶颈,内存带宽和缓存竞争才是主要限制,这时候增加并行度反而会导致总耗时上升。
优化建议
- 启用MySQL线程池插件(设置
thread_handling=pool-of-threads),优化连接线程的调度,减少线程切换开销。 - 避免同时执行大量全表扫描查询,若业务需要,可按
emp_no范围拆分查询,或使用只读副本分流查询压力。 - 通过
SHOW ENGINE INNODB STATUS查看缓冲池的latch等待情况,确认竞争来源。
内容的提问来源于stack exchange,提问作者MacGritsch
相关产品推荐
相关产品推荐

