如何利用预加载优化Laravel Model查询详解


Posted in PHP onAugust 11, 2017

前言

本文主要给大家介绍了关于利用预加载优化Laravel Model查询的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍:

介绍

对象关系映射(ORM)使数据库的工作变得非常简单。 在以面向对象的方式定义数据库关系时,可以轻松查询相关的模型数据,开发人员可能不会注意底层数据库调用。

下面将通过一些例子,进一步帮助您了解如何优化查询。

假设您从数据库收到了100个对象,并且每个记录都有1个关联模型(即belongsTo)。 默认使用ORM将产生101个查询; 如下所示:

//获取已发布的100条文章
$posts = Post::limit(100)->get(); //一次查询

$authors = array_map(function($post) {
 // 对作者模型生成查询
 return $post->author->name;
}, $posts);

我们在查询时没有告诉Post模型,我们还需要所有的作者,所以每次从单个Post模型实例获取作者的名字时,都会发生单独的查询。

array_maps时发生100次查询,加上先前一次查询,累计产生101次查询。

预加载

接下来,如果我们打算使用关联的模型数据,我们可以使用预加载将该101个查询总数减少到2个查询。 只需要告诉模型你需要什么来加载。如下:

//获取已发布的100条文章 - 并预加载文章对应作者
$posts = Post::with('author')->limit(100)->get();//2次查询

$authors = array_map(function($post) {
 // 对作者模型生成查询
 return $post->author->name;//这里讲不在产生查询
}, $posts);

如果你开启了sql日志,你将看到上述预加载将只会产生两条查询:

select * from `posts`
select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?) [1,2,3,4,5]

如果您有多个关联模型,则可以使用数组加载它们:

$posts = App\Post::with(['author', 'comments'])->get();

接下来我们重新定义如下关系

Post -> belongsTo -> Author //每个文章只属于一个用户
Author -> hasMany -> Post //每个用户拥有多个文章
Author -> hasOne -> Profile //每个用户只有一个简介

考虑下述情况:获取已发布文章所属作者的个人简介。

//获取所有文章 - 并预加载文章对应作者
$posts = App\Post::with('author')->get();//两次查询

//根据每个 `作者` 获取其简介
$posts->map(function ($post) {
 //虽然我们直接通过$author = $post->author不会产生查询,
 //但当调用$author->profile时,每次都会产生一个新查询
 return $post->author->profile;
});

假设上述App\Post::with('author')->get()有100条记录,将会产生多少条查询呢?

通过优化预加载,我们可以避免嵌套关系中的额外查询。

//获取所有文章 - 并预加载文章对应作者及每个作者对应de profile
$posts = App\Post::with('author.profile')->get();//三次查询

$posts->map(function ($post) {
 //不在产生新查询
 return $post->author->profile;
});

你可以打开你的sql日志看到对应的三条查询。

select * from `posts` 
select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?) [.....] 
select * from `profiles` where `profiles`.`author_id` in (?, ?, ?, ?, ?) [.....]

懒惰加载

有时候您可能只需要根据条件收集相关联的模型。 在这种情况下,您可以懒惰地调用相关数据的其他查询:

$posts = App\Post::all();//一次查询

$posts->load('author.profile');//两次查询
$posts->map(function ($post) {
 //不在产生新查询
 return $post->author->profile;
});

查看您的sql日志,总共看到三个查询,但只有调用$posts->load()时才会显示。

结论

希望您更加了解有关加载型号的更多信息,并了解其在更深层次上的工作原理。 Laravel相关的文档已经很全面了,希望额外的实践练习可以帮助您更有信心优化关系查询。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

原文译自eloquent-eager-loading,简化其前面构造数据部分。

PHP 相关文章推荐
在线短消息收发的程序,不用数据库
Oct 09 PHP
phpmyadmin安装时提示:Warning: require_once(./libraries/common.inc.php)错误解决办法
Aug 18 PHP
php cli 小技巧
Jun 03 PHP
php smarty模板引擎的6个小技巧
Apr 24 PHP
PHP使用gmdate实现将一个UNIX 时间格式化成GMT文本的方法
Mar 19 PHP
PHP学习笔记(二):变量详解
Apr 17 PHP
php跨服务器访问方法小结
May 12 PHP
PHP封装CURL扩展类实例
Jul 28 PHP
php调用自己java程序的方法详解
May 13 PHP
PHP中PDO连接数据库中各种DNS设置方法小结
May 13 PHP
PHP实现自动识别原编码并对字符串进行编码转换的方法
Jul 13 PHP
PHP基于ip2long实现IP转换整形
Dec 11 PHP
PHP实现的自定义图像居中裁剪函数示例【测试可用】
Aug 11 #PHP
Redis在Laravel项目中的应用实例详解
Aug 11 #PHP
PHP验证码无法显示的原因及解决办法
Aug 11 #PHP
php readfile()修改文件上传大小设置
Aug 11 #PHP
浅谈Laravel中的一个后期静态绑定
Aug 11 #PHP
浅谈PHP中new self()和new static()的区别
Aug 11 #PHP
php使用 readfile() 函数设置文件大小大小的方法
Aug 11 #PHP
You might like
php如何控制用户对图片的访问 PHP禁止图片盗链
2016/03/25 PHP
Thinkphp5框架中引入Markdown编辑器操作示例
2020/06/03 PHP
javascript页面动态显示时间变化示例代码
2013/12/18 Javascript
jQuery移除tr无效的解决方法(tr是动态添加)
2014/09/22 Javascript
JavaScript获取短信验证码(周期性)
2016/12/29 Javascript
bootstrap3 dialog 更强大、更灵活的模态框
2017/04/20 Javascript
bootstrap-table实现服务器分页的示例 (spring 后台)
2017/09/01 Javascript
Angular简单验证功能示例
2017/12/22 Javascript
原生JS实现多个小球碰撞反弹效果示例
2018/01/31 Javascript
原生JS实现网页手机音乐播放器 歌词同步播放的示例
2018/02/02 Javascript
详解redis在nodejs中的应用
2018/05/02 NodeJs
jQuery实现适用于移动端的跑马灯抽奖特效示例
2019/01/18 jQuery
深入了解query和params的使用区别
2019/06/24 Javascript
[03:00]2014DOTA2国际邀请赛 Titan淘汰潸然泪下Ohaiyo专访
2014/07/15 DOTA
Python实现计算文件夹下.h和.cpp文件的总行数
2015/04/23 Python
Python简单实现子网掩码转换的方法
2016/04/13 Python
Puppeteer使用示例详解
2019/06/20 Python
pygame实现成语填空游戏
2019/10/29 Python
HTML5语音识别标签写法附图
2013/11/18 HTML / CSS
HTML5 transform三维立方体实现360无死角三维旋转效果
2014/08/22 HTML / CSS
伦敦最有品味的百货:Liberty London
2016/11/12 全球购物
BLACKMORES澳洲官网:澳大利亚排名第一的保健品牌
2018/09/27 全球购物
在购买印度民族服饰:Soch
2020/09/15 全球购物
请解释virtual关键字的含义
2015/06/17 面试题
学校办公室主任职责
2013/12/27 职场文书
食品委托检验协议书范本
2014/09/12 职场文书
2014年十一国庆节爱国演讲稿
2014/09/23 职场文书
加强机关作风建设心得体会
2014/10/22 职场文书
研究生个人学年总结
2015/02/14 职场文书
大学生支教感言
2015/08/01 职场文书
让人感觉高大上的讲话稿怎么写?
2019/07/08 职场文书
小学生六年级作文之关于感恩
2019/08/16 职场文书
python 自动刷新网页的两种方法
2021/04/20 Python
python 解决微分方程的操作(数值解法)
2021/05/26 Python
SpringBoot+Redis实现布隆过滤器的示例代码
2022/03/17 Java/Android
angular异步验证器防抖实例详解
2022/03/31 Javascript