标题参考来源
大家好~
今天来简单认识一下 N+1 query 吧!
假设我们查询10篇文章与文章作者,
那麽这个查询将会做11次查询。
1次是查询10篇文章,
另外10次是查询文章的作者。
上述情况就是发生了 N+1 query。
另外在这篇文章内有用烤蛋糕的方式解释 N+1 query,
挺有趣的~
来试试如何引发 N+1 query 吧~
目前我的资料库内有10笔留言,
然後使用下方范例做关联查询。
use Illuminate\Support\Facades\DB;
public function index()
{
DB::listen(function ($query) {
var_dump($query->sql);
});
$messages = Message::all();
$messages->each->user;
return $messages;
}
为了方便测试,
我在该 function 内使用 DB::listen()
监听事件。
下图为测试结果:
如我们预期的发生 N+1 query 了~
那麽接下来让我们认识该如何避免发生 N+1 query 吧!
在我的认知内,
加载关联时用以下方式可以避免:
那麽来用 with()
解决刚刚发生的 N+1 query 吧~
public function index()
{
DB::listen(function ($query) {
var_dump($query->sql);
});
$messages = Message::with('user')->get();
return $messages;
}
也能用 load()
解决:
public function index()
{
DB::listen(function ($query) {
var_dump($query->sql);
});
$messages = Message::all();
$messages->load('user');
return $messages;
}
而 whenLoad()
就必须搭配 API Resources 一起使用,
whenLoad()
会判断有无加载关联,
有加载才会显示关联资料,
进而避免 N+1 query。
至於用法的话,
我在 Day07 时有用到 whenLoad()
,
有兴趣的夥伴可以参考一下~
在 Laravel 8 後,
有支援一种方式可以有效避免 N+1 query!
只要将 AppServiceProvider.php
的 boot()
中加入这一段:
Model::preventLazyLoading(! app()->isProduction());
完整使用方式如下:
use Illuminate\Support\ServiceProvider;
public function boot()
{
Model::preventLazyLoading(! app()->isProduction());
}
这样设置後,
Laravel 会直接 Disabling Lazy Loading,
之後只要遇到 N+1 query,
Laravel 就会直接回报错误讯息给你喔!
当资料量大时,
N+1 query 产生的大量且多余的查询,
会对我们的资料库造成效能上的负担。
只要我们在使用 ORM 时稍加留意,
就可以有效避免发生 N+1 query 喔~
大家明天见啦~
若文章有任何问题,
还请大家不吝赐教!
假设你做好了资料蒐集,你的公司也准备在香港开展建立Shopify网店的计划,那下一步应该怎麽做呢?当...
加入 Autocomplete 原本是打算做email与公司的匹配,不过觉得在这个的逻辑上打转,基本...
在Game_Map的update改成 就会发现角色在施放技能时做了一个小动作~ 接着把技能范围为自身...
这几天看了一些铁人赛的文章,看到一些很不错的文章,当然也看到很多不知所云的内容 观察整体趋势是劣币驱...
值得一题的是我是用Microsoft Edge浏览器顺利完成报名的, 我也不知道是什麽原因, 要准...