当前位置: 首页 > news >正文

15 个 Eloquent 高级技巧,瞬间提升你的 Laravel 应用性能

15 个 Eloquent 高级技巧,瞬间提升你的 Laravel 应用性能

Eloquent 的优雅语法很容易让人忽略性能问题,特别是当数据表增长到千万级别时。我在调优处理上亿记录的高并发系统过程中,总结了 15 个实战技巧——远不止基础的预加载——能把慢查询优化到毫秒级。

"真正掌握 Eloquent 不是靠魔法——而是理解它生成的 SQL。"

原文链接 15 个 Eloquent 高级技巧,瞬间提升你的 Laravel 应用性能

用 Raw Count 代替关联关系的完整加载

为什么重要:加载整个关联只为了计个数,内存和性能都会受影响。

// ❌ N+1 查询 + 模型实例化
$posts = Post::all();
foreach ($posts as $post) {echo $post->comments->count();
}// ✅ 使用 withCount
$posts = Post::select('id','title')->withCount('comments')->get();
foreach ($posts as $post) {echo $post->comments_count;
}

性能对比:10k 条文章从 500 ms 降到 8 ms

深度分页用 Cursor Pagination

为什么重要:OFFSET 分页的偏移量越大,性能越差。

// ❌ OFFSET 100k
$users = User::paginate(25);// ✅ 使用 cursorPaginate
$users = User::where('created_at','>','2023-01-01')->orderBy('id')->cursorPaginate(25);

生成的 SQL

-- 下一页
SELECT * FROM users WHERE id > ? ORDER BY id LIMIT 25;

优势:任何深度的分页都是恒定时间。

大量关联数据用分块预加载

为什么重要:一条 IN() 语句里塞 5 万个 ID,很容易超时。

Post::chunkById(200, fn($posts) =>$posts->load(['comments' => fn($q) =>$q->select('id','post_id','content')->latest()->limit(10)])
);

要点:分批加载关联数据,控制每批大小,内存占用更少。

JSON 聚合处理嵌套数据

为什么重要:一条查询替代多个 JOIN 和循环。

$users = User::selectRaw("users.*, JSON_AGG(JSON_BUILD_OBJECT('address', addresses.street,'orders', orders.total)
) AS user_data")
->leftJoin('addresses','users.id','addresses.user_id')
->leftJoin('orders','users.id','orders.user_id')
->groupBy('users.id')
->get()
->map(fn($u) => array_merge($u->toArray(),json_decode($u->user_data, true)
));

结果:彻底消除嵌套关联的 N+1 问题。

软删除用部分索引

为什么重要WHERE deleted_at IS NULL 需要专门的索引。

Schema::table('users', fn(Blueprint $t) =>$t->index(['deleted_at'], 'active_idx')->where('deleted_at','IS',null)
);// 查询会使用部分索引
User::whereNull('deleted_at')->get();

性能对比:20 万行数据从 1.2 s 降到 14 ms。

lazyById() 实现真正的流式处理

为什么重要:chunk() 用的是 OFFSET,大表上性能会越来越差。

User::where('last_login','<', now()->subYear())->lazyById(1000)->each->delete();

优势:在百万级以上的表上快 10 倍。

基于表达式的排序

为什么重要:按子表数据排序不用 JOIN,避免繁重的连接操作。

Post::orderByDesc(Comment::select('created_at')->whereColumn('post_id','posts.id')->latest()->limit(1)
)->get();

⏱ 瞬间获得"最近活跃"列表,无需 JOIN。

条件关联加载

为什么重要:一次性过滤父级和子级数据。

// 在模型中
public function activeSubscriptions() {return $this->subscriptions()->where('expires_at','>', now())->where('status','active');
}// 控制器中
$users = User::withWhereHas('activeSubscriptions')->get();

神奇之处:一条查询同时过滤父级和子级数据。

Update From Select

为什么重要:跨表原子更新,单条查询搞定。

DB::table('users')->join('teams','teams.owner_id','=','users.id')->where('teams.status','premium')->update(['users.plan'=>'premium']);

告别“查出来-循环-再更新”的笨办法。

物化视图处理重度聚合

为什么重要:对上千万行数据实时计算 SUM/AVG,基本会超时。

CREATE MATERIALIZED VIEW user_stats AS
SELECT user_id, SUM(amount) AS ltv, COUNT(*) AS orders
FROM orders GROUP BY user_id;REFRESH MATERIALIZED VIEW user_stats;
$stats = DB::table('user_stats')->where('user_id',$id)->first();

性能对比:LTV 查询从 2 s 降到 0.2 ms。

多列过滤用复合索引

为什么重要:正确的顺序避免全表扫描。

Schema::table('users', fn(Blueprint $t) =>$t->index(['state','city'])
);

注意:只有在单独查询 state 或同时查询 state 和 city 时才有效。

pluck/toBase 实现选择性实例化

为什么重要:只要 ID 却实例化整个模型,内存白白浪费。

$ids = User::active()->toBase()->pluck('id');

内存对比:每 1k 条记录从 1.5 MB 降到 50 KB。

事务中的行级锁

为什么重要:高并发下防止竞态条件。

DB::transaction(fn() =>tap(User::where('id',$id)->lockForUpdate()->first(), fn($u) =>$u->decrement('stock'))
);

关键:秒杀场景下保证库存更新不会乱。

计算属性用表达式列

为什么重要:把重复计算交给数据库处理。

User::selectRaw("*, (SELECT COUNT(*) FROM orders WHERE user_id=users.id
) AS order_count")->get();

替代方案:通过视图物化(见技巧 #10)。

地理空间索引和查询

为什么重要:在数十万个点中快速搜索"附近"。

Schema::table('places', fn(Blueprint $t) =>$t->point('loc')->spatialIndex()
);Place::selectDistance('loc',DB::raw($point))->whereDistance('loc',DB::raw($point),'<',10000)->get();

性能对比:50 万个位置从 1.5 s 降到 8 ms。

📊 大规模性能对比

技术 1 万条 100 万条 1000 万条
常规分页 5 ms 120 ms 1.2 s
Cursor 分页 5 ms 8 ms 10 ms
预加载 80 ms 800 ms 超时
分块预加载 85 ms 150 ms 300 ms
软删除扫描 20 ms 1.5 s 15 s
部分索引 1 ms 2 ms 3 ms

题外话:最近花了很久的时间零零散散的将 Laravel Livewire4 的文档翻译成了中文,如果对 Laravel Livewire 感兴趣,可以查看文档 Laravel Livewire4 中文文档

http://www.jsqmd.com/news/35507/

相关文章:

  • 2025年口碑好的北美专线国际空运认证资质齐全榜单
  • 今日八股——JVM篇 - 指南
  • 2025年比较好的赣州装修公司全包施工
  • 2025年口碑好的酒会活动策划用户满意度TOP榜单
  • 2025年质量好的企业环保咨询用户满意度TOP榜单
  • 2025年深圳婚姻纠纷律师联系电话推荐:本地口碑榜与使用须知
  • 2025年口碑好的成都标书行业精选榜
  • 2025年质量好的档案文件销毁品牌服务排行榜
  • 2025年中国离婚律所联系电话推荐:婚姻家事精品律所全收录
  • 2025年中国离婚房产律师联系电话推荐:经典案例与贴心沟通
  • 2025年热门的鹅卵石鱼池假山制作厂家推荐及采购参考
  • 2025年中国离婚房产律师联系电话推荐:快速对接专业团队
  • 2025年中国遗嘱继承律所联系电话推荐:全程陪伴省心传承
  • 2025年热门的校园智慧体育行业竞争力权威排行
  • 2025年评价高的上海液冷系统IDCE数据中心展合作伙伴
  • 2025年中国离婚律所联系电话推荐:全国分所即时响应
  • 2025年中国离婚律所联系电话推荐:家理领衔靠谱名单
  • 2025年北京离婚房产律师联系电话推荐:靠谱渠道与预约技巧
  • 【开题答辩过程】以《基于SpringBoot和Vue框架的智能宠物之家系统的设计与实现》为例,不会开题答辩的可以进来看看 - 指南
  • 2025年中国离婚财产分割律师联系电话推荐:实战经验与贴心建议
  • 2025年北京离婚房产律师联系电话推荐:专业团队与贴心服务
  • 2025年热门的钐钴永磁器件厂家推荐及采购指南
  • 2025年靠谱的零角度二段力铰链用户好评厂家排行
  • 2025-11-09 早报新闻
  • 2025年最佳独立站谷歌优化高转化效果榜
  • 2025年北京离婚律所联系电话推荐:口碑经验全盘点
  • 2025年中国房产继承律师联系电话推荐:热线直通与预约技巧
  • 2025年上海离婚律所联系电话推荐:本地口碑与案例解析
  • 2025年中国房产继承律师联系电话推荐:精选推荐与使用指南
  • 深入解析:毕业设计:Python+YOLOv5/8 鸟类识别系统 计算机视觉 深度学习(PySide6桌面端+生态观测 源码)✅