PHP 入门教程
3. 使用
PHP 性能优化
本教程共 65 篇 · 第 43 篇 · 更新于 2026-07-24 · 约 5 分钟阅读
PHPPHP8性能优化OPcache缓存生成器数据库优化
43. PHP 性能优化
本节目标:了解 PHP 常见的性能瓶颈,掌握 OPcache、缓存策略和代码层面的优化技巧。
性能优化不是 Premature Optimization(过早优化),而是在明确瓶颈后有的放矢。本章介绍投入产出比最高的几项优化。
43.1 OPcache:最重要的优化
PHP 默认每次请求都要把源码编译成字节码。OPcache 把编译结果缓存到内存,下次直接执行,性能提升可达数倍。
检查 OPcache 是否启用
<?php
if (extension_loaded("Zend OPcache")) {
echo "OPcache 已启用\n";
print_r(opcache_get_status());
} else {
echo "OPcache 未启用,请在 php.ini 中设置 zend_extension=opcache";
}
推荐配置
; php.ini
zend_extension=opcache
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.validate_timestamps=1
| 配置项 | 说明 |
|---|---|
opcache.memory_consumption | 缓存内存大小(MB) |
opcache.max_accelerated_files | 最大缓存文件数 |
opcache.revalidate_freq | 检查文件更新的频率(秒) |
Note生产环境
revalidate_freq可设为60或更高,减少文件检查开销。开发环境设为0或1保证即时更新。
43.2 缓存策略
数据缓存
把数据库查询结果缓存起来,避免重复查询:
<?php
function getUser(int $id): array {
$cacheFile = "cache/user_{$id}.json";
// 缓存 5 分钟
if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < 300) {
return json_decode(file_get_contents($cacheFile), true);
}
// 从数据库查询
$user = dbQuery("SELECT * FROM users WHERE id = ?", [$id]);
// 写入缓存
file_put_contents($cacheFile, json_encode($user));
return $user;
}
Tip生产环境推荐使用 Redis 或 Memcached 做分布式缓存,比文件缓存更快,且支持多服务器共享。
输出缓存
把整个页面的 HTML 缓存下来:
<?php
$cacheFile = "cache/page_" . md5($_SERVER["REQUEST_URI"]) . ".html";
if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < 3600) {
readfile($cacheFile);
exit;
}
// 开始输出缓冲
ob_start();
// 正常输出页面内容...
echo "<h1>动态内容</h1>";
// 保存到缓存
file_put_contents($cacheFile, ob_get_contents());
ob_end_flush();
43.3 代码层面优化
1. 优先使用单引号字符串
<?php
// 单引号不解析变量,略快
$name = '张三';
$greeting = 'Hello, world'; // 比 "Hello, world" 稍快
// 需要解析变量时用双引号或插值
$msg = "欢迎, {$name}";
2. 避免在循环内做重复操作
<?php
$count = count($array); // 先计算,不要在 for 条件里重复调用
for ($i = 0; $i < $count; $i++) {
// ...
}
// PHP 8 起 foreach 是最高效的方式
foreach ($array as $item) {
// ...
}
3. 使用 isset() 代替 array_key_exists()
<?php
// isset 更快,但在值为 null 时返回 false
if (isset($arr["key"])) { }
// array_key_exists 更精确,但稍慢
if (array_key_exists("key", $arr)) { }
4. 及时释放大变量
<?php
$hugeData = fetchLargeDataset();
process($hugeData);
unset($hugeData); // 及时释放内存
5. 使用生成器处理大数据
<?php
// 普通数组:所有数据一次性加载到内存
function readLines(string $file): array {
return file($file); // 大文件会内存溢出
}
// 生成器:逐行读取,省内存
function readLinesGenerator(string $file): Generator {
$fp = fopen($file, "r");
while (($line = fgets($fp)) !== false) {
yield trim($line);
}
fclose($fp);
}
foreach (readLinesGenerator("big.log") as $line) {
// 处理每一行,内存占用恒定
}
NotePHP 8 进一步提升了生成器性能。处理大文件、大数据集时,生成器是首选方案。
43.4 数据库优化
- 加索引:WHERE、JOIN、ORDER BY 的字段要有索引
- 只查需要的字段:避免
SELECT * - 分页优化:大数据量时用覆盖索引或延迟关联
- 连接复用:使用持久连接(PDO
PDO::ATTR_PERSISTENT)
43.5 使用性能分析工具
找到真正的瓶颈才能有效优化:
<?php
// 简单的耗时测量
$start = microtime(true);
// 要测试的代码...
$end = microtime(true);
echo "耗时:" . round(($end - $start) * 1000, 2) . " 毫秒";
生产环境推荐:
- Xdebug Profiler:生成性能分析报告
- Blackfire.io:专业的 PHP 性能分析服务
- Tideways:开源的 APM 工具
来源:参考了 GitHub「php-the-right-way」相关章节、PHP 官方性能指南等,改写后所得。