ThinkPHP6应对1万并发需聚焦SQL性能优化:先通过EXPLAIN和慢日志定位全表扫描,为WHERE字段建索引;高频查询必须显式调用cache()并前置;固定查询改用PDO预编译;启用连接池与读写分离;同步调优MySQL的innodb_buffer_pool_size、max_connections等参数。

ThinkPHP6处理1万并发时出现MySQL慢查询,核心不是“扛住并发”,而是让每条查询足够快、足够轻、足够可控。1万并发下若单条SQL平均耗时50ms,理论QPS就卡在200,远达不到目标;真正可行的路径是:把高频查询压到1–3ms内,再配合连接池、缓存和异步卸载,才能稳住高并发。
先确认是不是真慢,还是被缓存掩盖了
清理缓存后查询变慢,往往不是缓存“失效”导致变慢,而是原本就慢的SQL被缓存挡住了——现在裸奔暴露了问题。别急着加Redis或换数据库,先做三件事:
- 在database.php配置中开启
'sql_explain' => true,复现一次请求,看日志里是否有EXPLAIN输出,重点检查type字段是否为ALL(全表扫描) - 临时开启MySQL慢日志:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 0.1;,复现请求后查slow.log,确认真实耗时 - 用
SHOW INDEX FROM your_table核对WHERE常用字段(如mobile、user_id、status)是否建索引;没索引就立刻加:ALTER TABLE user ADD INDEX idx_mobile (mobile);
高频查询必须走缓存,但得用对方式
ThinkPHP6的cache()不是自动开关,它只对显式调用且作用于Query对象才生效。常见错误写法:->count()->cache(300)(count返回int,无法链式调用cache)。
- 正确写法:
UserModel::where('id', $id)->cache(3600)->find(),cache()必须出现在find()或select()之前 - 自定义key更安全:
cache('user_'.$id, 3600),避免框架MD5生成的key因SQL空格或数据库前缀不同而冲突 - 对列表页等复杂查询,建议封装成独立方法+手动缓存:
Cache::remember('user_list_status_1', 600, function () { return UserModel::where('status', 1)->select(); });
高并发读写分离与预编译落地
默认Db查询走字符串拼接,每次都要解析SQL、生成执行计划,1万并发下开销陡增。关键优化点:
- 对固定结构的高频查询(如根据手机号查用户),绕过Query类,直接用PDO预编译:
$pdo = Db::connect()->getPdo();<br>$stmt = $pdo->prepare('SELECT id,name,status FROM user WHERE mobile = ? AND status = ?');<br>$stmt->execute([$phone, 1]);<br>$result = $stmt->fetch(PDO::FETCH_ASSOC); - 启用连接池(需Swoole环境):在database.php中配置
'pool_size' => 200,避免反复创建销毁连接 - 读写分离不是可选项:主库只写,从库承担95%以上查询;ThinkPHP6支持
Db::name('user')->useReadConn()->select()手动指定读库
别忽略MySQL服务端配置
应用层再优化,也架不住MySQL本身瓶颈。1万并发下必须调优以下几项:
-
innodb_buffer_pool_size设为物理内存的60–70%,确保热数据常驻内存 - 开启
log_queries_not_using_indexes = ON,主动捕获漏网之鱼 - 调整
max_connections至3000+(需同步调大系统文件句柄数),并设置wait_timeout = 60防连接堆积 - 定期运行
ANALYZE TABLE user;更新统计信息,帮优化器选对执行计划
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











