- 预加载
- 预加载,就是解决关联查询中产生的N+1次查询带来的资源消耗
- 我们要获取所有书籍的作者(或拥有者),普通查询方案如下:
//获取所有书籍列表
$books = Book::all();
//遍历每一本书
foreach ($books as $book){
//每一本书的关联用户姓名
echo $book->user->username;
}
PS: 关联查询是,每遍历一次就会执行一遍SQL语句,导致性能欠佳;
PS: 所谓N+1条,就是起初获取全部数据的1条和,遍历的N条;
c. 使用with()关键字,进行预载入设置,提前将SQL整合:
//with关键字预载入
$books = Book::with(‘user’)->get();
foreach ($books as $book){
echo $book->user->username;
}
PS: 此时的SQL执行数目为:1+1条;也支持数组多个关联with[‘book’, ‘prifile’];
PS: 预加载也可以设置显示的列;
//预载入设置指定的列
$books = Book::with(‘user:id,username’)->get();
d. 如果每次都必须使用预载入进行关联查询,可以在模型中定义;
protected $with = [‘user’];
PS: 此时就可以像最初那样写代码,而不需要使用with()方法了;
e. 为了演示方便,暂时取消模型$with, 再看下预载入结合筛选:(闭包查询)
$books = Book::with([‘user’=>function ($query) {
$query->where(‘id’, 20);
}])->get();
foreach($books as $book){<br /> if($book->user != null){<br /> echo $book->user->username;<br /> }<br /> }<br />PS: 预载入筛选不可使用limit、take方法;<br /> f. 有时,可能会产生逻辑判断是否查询数据,但预加载会提前关联执行;<br /> g. 这样,会导致资源性能浪费,这时,可以采用延迟预载入;<br />$books = Book::all();
if(true){<br /> $books = $books->load('user'); //load(['user' => function () {}])<br /> foreach ($books as $book){<br /> echo $book->user->username;<br /> }<br /> }<br /> h. 使用loadCount()方法,可以实现延迟关联统计:<br />$users = User::all();<br /> if(true){<br /> $users = $users->loadCount('book');<br /> }<br /> return $users;