PHP PDO 性能压测实践总结

6次阅读

pdo性能取决于连接管理、sql写法、预处理方式、错误处理及mysql配置;应启用持久连接、复用连接对象、按场景合理使用预处理、指定高效fetch模式、设errmode_exception并配合日志分析。

PHP PDO 性能压测实践总结

php PDO 本身不决定性能上限,真正影响压测结果的是连接管理、SQL 写法、预处理使用方式、错误处理策略以及底层 MySQL 配置。一次真实的压测,往往暴露的是应用层设计问题,而非 PDO 慢。

连接复用比“用完就关”更关键

PDO 默认是短连接,每次 new PDO() 都会建立新 TCP 连接,高并发下容易打满连接数或触发三次握手延迟。生产环境必须启用持久连接(PDO::ATTR_PERSISTENT),但要注意:

  • 持久连接由 PHP-FPM 进程持有,不能在脚本结束时主动 close,需依赖进程回收
  • MySQL 的 wait_timeout 要大于 PHP-FPM 的 max_request 或 idle timeout,否则连接被服务端断开后,PDO 不会自动重连,下次 query 直接报错
  • 不要在循环里反复 new PDO,应全局单例或容器注入,连接对象复用到底层语句执行

预处理不是万能的,要分场景用

prepare + execute 确实防 SQL 注入且能复用执行计划,但并非所有查询都适合:

  • 简单 select id FROM user WHERE id = ?(主键等值)——预处理收益明显,MySQL 可缓存执行计划
  • SELECT * FROM log WHERE created_at > ? ORDER BY id DESC LIMIT ?, ? ——带 LIMIT 和动态偏移的分页,预处理无法避免全表扫描,重点应是加索引和优化分页逻辑
  • INSERT INTO t (a,b,c) VALUES (?,?,?) ——批量插入时,应改用 INSERT … VALUES (…),(…),(…) 单条语句 + execute(array_merge(…)),比循环 execute 快 3–5 倍

fetch 模式直接影响内存与速度

默认 PDO::FETCH_BOTH 同时返回数字索引和关联键,内存翻倍且解析慢。压测中应显式指定:

立即学习PHP免费学习笔记(深入)”;

  • 只读字段名?用 PDO::FETCH_ASSOC(最常用)
  • 只按顺序取值?用 PDO::FETCH_NUM(最快,尤其配合 list() 解构)
  • 查单行单字段(如 count(*))?直接 fetchColumn(),避免构造数组开销
  • 大量数据导出?禁用 fetchAll(),改用 fetch() 循环 + unset() 中间变量,防止 OOM

错误模式别设成 SILENT

压测期间若设 PDO::ATTR_ERRMODE = PDO::ERRMODE_SILENT,SQL 报错会被吞掉,只返回 false,极易掩盖死锁、超时、主从延迟导致的脏读等问题。正确做法:

  • 开发/压测环境统一设为 PDO::ERRMODE_EXCEPTION,让异常抛出,配合日志记录完整 SQL 和绑定参数
  • 对明确可预期的失败(如用户不存在),用 try/catch 包裹,不要依赖 false 判断
  • 开启 MySQL general_log 或 slow_query_log,交叉验证 PDO 执行的 SQL 是否真被发出、是否被优化器改写

不复杂但容易忽略。压测不是比谁 QPS 高,而是看在目标并发下,平均延时稳不稳定、错误率有没有突增、数据库负载是否均衡。PDO 是工具,用对了,它不会拖后腿。

text=ZqhQzanResources