Laravel Eloquent orm的性能 - N+1 查询问题
我知道这个问题 N+1 是影响我项目性能的问题之一,我发现这篇文章包含了原因
https://laravel-news.com/laravel-n1-query-problems
和解决方案 问题,我想和你分享,因为这个话题很重要
四个案例明确问题并解决问题
案例 1.“常规”N+1 查询
// app/Models/Book.php
class Book extends Model
{
public function author()
{
return $this->belongsTo(Author::class);
}
}
// Then, in some Controller:
$books = Book::all();
foreach ($books as $book) {
echo $book->author->name;
}
固定
// Instead of
$books = Book::all();
// You should do
$books = Book::with('author')->get();
案例 2. 两个重要符号
public function index()
{
$authors = Author::with('books')->get();
return view('authors.index', compact('authors'));
}
// Blade
@foreach($authors as $author)
<tr>
<td>{{ $author->name }}</td>
<td>{{ $author->books()->count() }}</td>
</tr>
@endforeach
因此,关系方法将为每个作者查询数据库。 但是如果你加载数据,不带 () 符号,它会成功使用急切加载的数据 $author->books
使固定
// Controller
$authors = Author::withCount('books')->get();
// Blade
{{ $author->books_count }}
案例 3. Accessor 中的“隐藏”关系
// Controller
public function index()
{
$authors = Author::all();
return view('authors.index', compact('authors'));
}
// Blade
@foreach($authors as $author)
<tr>
<td>{{ $author->name }}</td>
<td>{{ $author->is_active ? 'Yes' : 'No' }}</td>
</tr>
@endforeach
“is_active”是在 Eloquent 模型中定义的
use Illuminate\Database\Eloquent\Casts\Attribute;
class Author extends Model
{
public function isActive(): Attribute
{
return Attribute::make(
get: fn () => $this->books->count() > 0,
);
}
}
案例 4. 小心 with Packages
Laravel 有一个很棒的软件包生态系统,但有时“盲目地”使用它们的功能是很危险的。 如果您不小心,您可能会遇到意外的 N+1 查询。
针对 N+1 查询的内置解决方案
从 Laravel 8.43 开始,框架
https://laravel-news.com/disable-eloquent-lazy-loading-during-development
除了 Laravel Debugbar 进行检查,还可以添加代码来预防这个问题
需要在
app/Providers/AppServiceProvider.php
添加两行代码
use Illuminate\Database\Eloquent\Model;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Model::preventLazyLoading(! app()->isProduction());
}
}
现在,如果您启动任何包含 N+1 查询问题的页面,您将看到一个错误页面
我只解释了重点,但要深入,必须增加文章并从中受益。
转:
https://dev.to/morcosgad/eloquent-performance-n1-query-problems-laravel-5ahj
相关文章