• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

什么是-N1-问题以及如何解决

php 搞代码 3年前 (2022-02-28) 17次浏览 已收录 0个评论
文章目录[隐藏]

N+1 是ORM(对象关系映射)世界中的一个问题。

在介绍什么是N+1问题之前,首先思考一个问题:

假如当初有一个用户表和一个余额表,这两个表通过user_id进行关联。当初有一个需要是查问年龄大于18岁的用户,以及用户各自的余额

这个问题并不难,但对于老手而言,可能经常会犯的一个谬误就是在循环中进行查问。

$users = User::where("age", ">", 18)->select();
foreach($users as $user){
  $balance = User::getFieldByUserId($user->user_id, "balance");
  $user['balance'] = $balance;
}

这样做是十分蹩脚的,数据量小还少,在数据量较大的状况下,是十分耗费数据库性能的。

通过Mysql 查问日志,能够看到查问用户表是一次,因为有四个合乎该条件的用户,查问用户表关联的余额表是四次。

N+1问题就是这样产生的:查问主表是一次,查问出N 条记录,依据这N 条记录,查问关联的副(从)表,共须要N 次。所以,应该叫1+N 问题更适合一些。

其实,如果略微理解一点SQL,基本不必这么麻烦,间接应用JOIN 一次就搞定了。

有时候是不是感觉ORM 也挺碍事的。

对于这类问题,ORM 其实为咱们提供了相应的计划,那就是应用with

with

$users = User::where("age", ">", 18)
        ->with("hasBalance")
        ->select();

hasBalance 是什么呢?

它是在User模型中定义的一个办法:

class User extends Model
{
    //  ...
    
    public function hasBalance()
    {
          return $this->hasOne(Balance::class, "user_id", "user_id");
    }
}

通过这个办法让User 模型与Balance 模型进行一对一关联。

当初再来看一下Mysql 的查问日志:

能够很分明的看到,总查问次数由原来的1+N 变成了当初的1+1

总结

N+1 问题是什么?会造成什么影响?应该如何解决?

  1. 执行一次查问获取N 条主数据后,因为关联引起的执行N 次查问从数据
  2. 带来了不必要的查问开销
  3. 能够通过框架 ORM 自带的with 去解决

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:什么是-N1-问题以及如何解决

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址