性能优化是 Laravel 应用上线后绕不开的课题。一个未经优化的 Laravel 应用可能在开发阶段跑得飞快,但一旦面对真实用户流量,各种瓶颈就会逐一浮现。本文将从一个典型的 Laravel 请求生命周期出发,逐层梳理性能优化的关键环节,并给出可落地的优化方案。
绝大多数 Laravel 应用的性能瓶颈都出在数据库层。优化数据库查询往往能带来立竿见影的效果。
N+1 查询是 Laravel 中最常见的性能杀手,通常发生在 Eloquent 关联关系中:
// ❌ 错误写法:每次循环都会执行一次 SQL 查询
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name;
}
使用 with() 预加载可以一键解决问题:
// ✅ 正确写法:只需 2 条 SQL 查询
$posts = Post::with('author')->get();
foreach ($posts as $post) {
echo $post->author->name;
}
对于更深层的嵌套关联,可以使用点语法:
$posts = Post::with('author.profile', 'comments.user')->get();
索引是数据库优化的基础手段。通过 EXPLAIN 或 Laravel Debugbar 分析慢查询,找到缺少索引的字段:
// 在迁移文件中添加索引
Schema::table('posts', function (Blueprint $table) {
$table->index('status'); // 单列索引
$table->index(['status', 'type']); // 复合索引
});
重点关注以下场景:
WHERE 子句中使用的字段ORDER BY 排序的字段JOIN 关联的字段GROUP BY 中的字段// 只取需要的字段,避免 SELECT *
$posts = Post::select('id', 'title', 'created_at')->get();
// 使用 chunk 分批处理大数据集
Post::chunk(200, function ($posts) {
foreach ($posts as $post) {
// 处理逻辑
}
});
// 使用 lazy 惰性加载(需要 PHP 8.0+)
$posts = Post::lazy(200)->each(function ($post) {
// 处理逻辑
});
Laravel 的缓存系统支持多种驱动,生产环境推荐使用 Redis 或 Memcached。
对于不经常变化的数据,缓存查询结果是最直接的方式:
// 缓存查询结果 10 分钟
$posts = Cache::remember('posts.active', 600, function () {
return Post::with('author')->where('status', 'published')->get();
});
对于内容变化较少的页面,可以用 HTTP 缓存中间件:
// 在路由中应用缓存中间件
Route::middleware(['cache.headers:public;max_age=3600;etag'])->group(function () {
Route::get('/sitemap.xml', [SitemapController::class, 'index']);
});
Laravel 的缓存标签功能可以批量清除相关缓存:
// 存入带标签的缓存
Cache::tags(['posts', 'author:' . $authorId])->put('posts.active', $posts, 600);
// 文章更新时,清除相关标签下的所有缓存
Cache::tags(['posts', 'author:' . $authorId])->flush();
耗时操作应当通过队列异步执行,避免阻塞 HTTP 响应。
生产环境推荐使用 Redis 或数据库作为队列驱动:
# .env 配置 QUEUE_CONNECTION=redis REDIS_QUEUE=default
// 控制器中不再直接执行耗时操作
public function store(Request $request)
{
$video = Video::create($request->validated());
// 将视频转码任务推入队列
ProcessVideo::dispatch($video);
return response()->json($video, 201);
}
生产环境建议使用 Supervisor 管理队列 Worker:
[program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /path/to/project/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600 autostart=true autorestart=true numprocs=4 user=forge
numprocs=4 表示启动 4 个 Worker 进程,充分利用 CPU 多核能力。
PHP 8.x 的 OPcache 配置建议:
; php.ini opcache.enable=1 opcache.memory_consumption=256 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=20000 opcache.revalidate_freq=60 opcache.fast_shutdown=1 opcache.validate_timestamps=0
在部署时通过 artisan optimize 生成配置和服务缓存:
php artisan optimize php artisan route:cache php artisan view:cache php artisan config:cache
PHP 8.0 引入的 JIT 可进一步提升 CPU 密集型任务的性能:
opcache.jit=tracing opcache.jit_buffer_size=100M
Laravel 默认使用 Vite 进行前端构建,利用代码分割减少首屏加载体积:
// vite.config.js
export default defineConfig({
plugins: [laravel()],
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'axios', 'lodash'],
ui: ['element-plus', '@fortawesome/fontawesome-free'],
},
},
},
},
});
对于大型 SPA 应用,使用动态导入实现组件懒加载:
// 路由懒加载
const Dashboard = () => import('./Pages/Dashboard.vue');
const Reports = () => import('./Pages/Reports.vue');
优化不是一劳永逸的,需要持续监控:
# 安装 Telescope composer require laravel/telescope --dev php artisan telescope:install php artisan migrate
Laravel 性能优化是一个系统工程,从数据库查询、缓存策略、队列异步、PHP 配置到前端资源,每一环都值得关注。建议按照以下优先级依次推进:
先用 Debugbar / Telescope 定位瓶颈
优化数据库查询(N+1、索引、字段选择)
引入缓存策略(查询缓存、页面缓存)
将耗时操作异步化(队列)
调整 PHP 配置(OPcache、JIT)
优化前端资源(代码分割、懒加载)
每一步投入都能带来可量化的性能提升,而最关键的是:永远基于数据做优化,不要猜测瓶颈所在。