post-image

Eager Loading là gì ?

Tổng quan

Trong bài viết này chúng ta hãy cùng nhau tìm hiểu về khái niệm Eager Loading – kỹ thuật giúp chúng ta xử lý vấn đề N + 1 câu truy vấn.

N+1 câu truy vấn là gì?

Khi chúng ta sử dụng eloquent relationships trong laravel, mặc định eloquent relationships sẽ ở chế độ “lazy” khi load lên tất cả các model quan hệ (relation). Để minh họa vấn đề truy vấn N + 1, hãy xem xét một model Book có quan hệ với Author:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    /**
     * Get the author that wrote the book.
     */
    public function author()
    {
        return $this->belongsTo('App\Author');
    }
}

Bây giờ, hãy lấy tất cả các cuốn sách và tác giả của chúng:

$books = App\Book::all();

foreach ($books as $book) {
    echo $book->author->name;
}
  • Vòng lặp này sẽ thực hiện 1 truy vấn để truy xuất tất cả các sách trên bảng, sau đó một truy vấn khác cho mỗi cuốn sách để truy xuất tác giả. Vì vậy, nếu chúng ta có 25 cuốn sách, vòng lặp này sẽ chạy 26 truy vấn: 1 cho cuốn sách gốc và 25 truy vấn bổ sung để truy xuất tác giả của mỗi cuốn sách.

Thật là kinh khủng nếu dữ liệu của chúng ta có hàng triệu cuốn sách. Tốc độ truy vấn sẽ rất lâu và khiến cho người dùng khó chịu khi phải chờ đợi, nhưng thật may khi ta có Eager Loading để giải quyết vấn đề này.

Sử dụng Eager Loading để giải quyết vấn đề N+1 truy vấn

Chúng ta có thể sử dụng nó để số lượng xuống chỉ còn 2 truy vấn. Khi truy vấn, bạn có thể chỉ định những mối quan hệ nào sẽ được eager loaded bằng phương thức with():

$books = App\Book::with('author')->get();

foreach ($books as $book) {
    echo $book->author->name;
}

Đối với thao tác này, chỉ có hai truy vấn sẽ được thực hiện:

select * from books

select * from authors where id in (1, 2, 3, 4, 5, ...)

Truy vấn nhiều quan hệ

Đôi khi bạn có thể cần lấy một số mối quan hệ khác nhau trong một truy vấn. Để làm như vậy, chỉ cần truyền các đối số bổ sung cho phương thức with:

$books = App\Book::with('author', 'publisher')->get();

Constraining Eager Loads

Đôi khi bạn có thể muốn Eager Loading một quan hệ, nhưng cũng chỉ định các ràng buộc truy vấn bổ sung cho truy vấn Eager Loading. Đây là một ví dụ:

$users = App\User::with(['posts' => function ($query) {
    $query->where('title', 'like', '%first%');

}])->get();

Trong ví dụ này, Eloquent sẽ chỉ Eager Loading các bài đăng trong đó cột title của bài đăng có chứa từ đó first.

Lazy Eager Loading

Đôi khi bạn có thể cần Eager Loading một mối quan hệ sau khi đối tượng cha đã được lấy. Điều này giúp chúng ta có quyền quyết định có chạy câu query thứ 2 để load các mối quan hệ hay không với các điều kiện mở rộng.

$books = App\Book::all();

if ($someCondition) {
    $books->load('author', 'publisher');
}

Nguồn: https://viblo.asia/p/laravel-eager-loading-lap-trinh-vien-laravel-can-phai-biet-Az45bY3qlxY

Đọc thêm: SQL vs NoSQL

Leave a Reply

Your email address will not be published.