Day11-Database——效能的储备足够吗?-N+1 query

标题参考来源
大家好~
今天来简单认识一下 N+1 query 吧!

什麽是 N+1 query 呢?

假设我们查询10篇文章与文章作者,
那麽这个查询将会做11次查询。
1次是查询10篇文章,
另外10次是查询文章的作者。
上述情况就是发生了 N+1 query。

另外在这篇文章内有用烤蛋糕的方式解释 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 吧!

如何避免 N+1 query?

在我的认知内,
加载关联时用以下方式可以避免:

  1. Eloquent: Relationships——with()
  2. Eloquent: Collections——load()
  3. Eloquent: API Resources——whenLoad()

那麽来用 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.phpboot() 中加入这一段:

Model::preventLazyLoading(! app()->isProduction());

完整使用方式如下:

app/Providers/AppServiceProvider.php
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 喔~

大家明天见啦~
若文章有任何问题,
还请大家不吝赐教!

参考资料:


<<:  Flutter体验 Day 18-路由导览v2

>>:  心血管疾病notebook使用MLFlow做记录

建立香港Shopify网店需要思考的7个因素

假设你做好了资料蒐集,你的公司也准备在香港开展建立Shopify网店的计划,那下一步应该怎麽做呢?当...

「Wordpress 外挂开发」代客下单最终章,观察经手人

加入 Autocomplete 原本是打算做email与公司的匹配,不过觉得在这个的逻辑上打转,基本...

[Day29] 动画篇6

在Game_Map的update改成 就会发现角色在施放技能时做了一个小动作~ 接着把技能范围为自身...

Day 24-请问我可以 taint 你的文章强迫你重写吗?state manipulation 之六:terraform taint

这几天看了一些铁人赛的文章,看到一些很不错的文章,当然也看到很多不知所云的内容 观察整体趋势是劣币驱...

Day 14 - AI-900 认证心得(2) - 考试

值得一题的是我是用Microsoft Edge浏览器顺利完成报名的, 我也不知道是什麽原因, 要准...