性能优化技巧
性能优化是提升用户体验的关键。本文介绍实用的 PHP 性能优化方法。
1. 使用适当的数据结构
php
// ❌ 低效:使用数组存储键值对进行频繁查找
$users = [['id' => 1, 'name' => '张三'], ['id' => 2, 'name' => '李四']];
foreach ($users as $user) {
if ($user['id'] == $searchId) { /* ... */ }
}
// ✅ 高效:使用关联数组
$userMap = [1 => '张三', 2 => '李四'];
$name = $userMap[$searchId] ?? null;
// isset 比 array_key_exists 快
if (isset($arr['key'])) { } // ✅ 更快
if (array_key_exists('key', $arr)) { } // 较慢
// 空数组检查
if (!$arr) { } // ✅ 最快
if (empty($arr)) { } // 稍慢
if (count($arr) === 0) { } // 最慢2. 字符串操作优化
php
// 单引号比双引号快(无变量插值时)
$str = 'hello world'; // ✅ 更快
$str = "hello world"; // PHP 会解析变量
// 字符串连接
$name = $first . ' ' . $last; // ✅ 少量连接
$name = "$first $last"; // 可读性更好
// 大量连接使用数组
$parts = [];
foreach ($items as $item) {
$parts[] = process($item);
}
$result = implode('', $parts); // ✅ 比 .= 快3. 循环优化
php
// 缓存数组长度
$count = count($array); // ✅ 只计算一次
for ($i = 0; $i < $count; $i++) { }
// 优先使用 foreach
foreach ($array as $key => $value) { } // ✅ PHP 中通常最快
// 避免在循环中调用函数
$len = strlen($str); // ✅ 提取到循环外
for ($i = 0; $i < $len; $i++) { }
// 预分配数组容量(大数据量)
$result = new SplFixedArray(10000); // 固定大小数组4. 文件操作优化
php
// 读取大文件
// ❌ 内存占用高
$content = file_get_contents('huge.log');
// ✅ 流式读取
$handle = fopen('huge.log', 'r');
while (($line = fgets($handle)) !== false) {
process($line);
}
fclose($handle);
// 包含文件优化
// ✅ 使用绝对路径
require_once __DIR__ . '/config.php';
// 自动加载优化
// ✅ 使用 Composer 优化后的自动加载
// composer dump-autoload --optimize5. 数据库查询优化
php
// ✅ 批量插入代替单条插入
$data = [
['name' => '张三', 'age' => 20],
['name' => '李四', 'age' => 25],
];
$pdo->prepare("INSERT INTO users (name, age) VALUES (?, ?)");
foreach ($data as $row) {
$stmt->execute([$row['name'], $row['age']]);
}
// ✅ 使用 JOIN 代替 N+1 查询
// ❌ 低效:循环查询
foreach ($users as $user) {
$orders = fetchOrders($user['id']); // N次查询
}
// ✅ 高效:一次 JOIN 查询
$stmt = $pdo->query("
SELECT u.*, o.id as order_id, o.amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
");6. 使用 Opcode 缓存
php
// ✅ 启用 OPcache(php.ini)
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0 // 生产环境
// 使用 APCu 做数据缓存
apcu_store('config', $config, 3600);
$config = apcu_fetch('config');7. 延迟加载与懒加载
php
class UserService {
private $db = null;
// ✅ 延迟初始化
private function getDb() {
if ($this->db === null) {
$this->db = new PDO('...');
}
return $this->db;
}
public function getUser($id) {
$stmt = $this->getDb()->prepare("SELECT * FROM users WHERE id = ?");
// ...
}
}注意事项
- 先分析再优化:使用 Xdebug 或 Blackfire 找出真正的瓶颈
- 避免过早优化:清晰的代码比微优化更重要
- 内存管理:注意循环引用可能导致内存泄漏
- 缓存策略:合理设计缓存,比代码优化效果更明显