全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货

什么是N+1问题,如何解决 Laravel 的 N+1 问题?

发布时间:2023-10-11 16:47:26
发布人:xqq

一、N+1问题

介绍

在基本级别,ORM 是 “懒惰” 加载相关的模型数据。但是,ORM 应该如何知道你的意图?在查询模型后,您可能永远不会真正使用相关模型的数据。不优化查询被称为 “N + 1” 问题。当您使用对象来表示查询时,您可能在不知情的情况下进行查询。

想象一下,您收到了100个来自数据库的对象,并且每条记录都有1个关联的模型(即belongsTo)。使用ORM默认会产生101条查询; 对原始100条记录 进行一次查询,如果访问了模型对象上的相关数据,则对每条记录进行附加查询。在伪代码中,假设您要列出所有已发布帖子的发布作者。从一组帖子(每个帖子有一位作者),您可以得到一个作者姓名列表,如下所示:

$posts = Post::published()->get(); // 一次查询

$authors = array_map(function($post) {

    // 生成对作者模型的查询

    return $post->author->name;

}, $posts);

我们并没有告诉模型我们需要所有作者,因此每次从各个Post 模型实例中获取作者姓名时都会发生单独的查询 。

解决

预加载功能

使用with()方法指定想要预加载的关联:

$users = User::where(“age”, “>”, 18)

        ->with(“hasBalance”)

        ->select();

hasBalance 是什么呢?

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

class User extends Model

{

    //  …

    // User模型与Balance 模型进行一对一关联

    public function hasBalance()

    {

          return $this->hasOne(Balance::class, “user_id”, “user_id”);

    }

}

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

延伸阅读:

二、N+1 问题由来

假设需要现在需要查找模型 A 的 n 条数据,而模型 A 又关联了另外多个的模型,这里假设 A 关联了模型 B 和 C. 现在需要查找 n 条 A 的记录(这里需要 1 条 SQL 语句,例如 select * from A ),同时把这 n 条记录关联的 B, C 记录也查出来(这里需要 n 条查询 B 的语句和 n 条查询 C 的语句),于是最后需要的 SQL 语句数目为 2n + 1。

将 2n 抽象出来,假设需要查找的是 n 条 A 的记录(count(SQL) = 1),同时需要把与 A 关联的 k 个模型的记录也查找处理出来( count(SQL) = n * k ), 设 n * k = N, 最后查询的 SQL 语句数目,即 N + 1。

#it技术干货

相关文章

Jetpack Compose到底是什么?

Jetpack Compose到底是什么?

2023-10-11
什么是Android单元测试?

什么是Android单元测试?

2023-10-11
Python10行以内代码能有什么高端操作?

Python10行以内代码能有什么高端操作?

2023-10-11
node.js可以用来做什么?

node.js可以用来做什么?

2023-10-11

最新文章

常见网络安全面试题:Windows常用的命令有哪些?

常见网络安全面试题:Windows常用的命令有哪些?

2023-10-09
常见网络安全面试题:根据设备告警如何展开排查?

常见网络安全面试题:根据设备告警如何展开排查?

2023-10-09
常见网络安全面试题:mysql加固呢?(数据库加固)

常见网络安全面试题:mysql加固呢?(数据库加固)

2023-10-09
常见网络安全面试题:windows和linux加固?(操作系统加固)

常见网络安全面试题:windows和linux加固?(操作系统加固)

2023-10-09
在线咨询 免费试学 教程领取