Giới thiệu

Trong các dự án Laravel, Eloquent ORM là công cụ mạnh mẽ giúp tương tác với cơ sở dữ liệu một cách trực quan. Tuy nhiên, khi mô hình dữ liệu phức tạp hoặc dữ liệu lượng lớn, các truy vấn Eloquent có thể gây ra hiện tượng "N+1 query" và làm giảm hiệu năng đáng kể. Bài viết này sẽ chia sẻ các kỹ thuật tối ưu truy vấn Eloquent thực tiễn, giúp giảm thời gian phản hồi và tiết kiệm tài nguyên máy chủ.

Kỹ thuật tối ưu truy vấn Eloquent

1. Eager Loading để tránh N+1 query

Thay vì tải quan hệ một cách lười (lazy loading) trong vòng lặp, hãy sử dụng with() để tải trước các quan hệ cần thiết.

$posts = App\Models\Post::with('comments', 'author')->where('status', 'published')->get();

Khi cần lọc quan hệ, whereHas() hoặc withWhereHas() sẽ giúp giảm số lượng bản ghi trả về.

2. Chỉ chọn các cột cần thiết

Việc lấy toàn bộ cột (*) làm tăng tải dữ liệu không cần thiết. Sử dụng select() để giới hạn trường.

$users = App\Models\User::select('id', 'name', 'email')
    ->where('active', true)
    ->get();

3. Sử dụng Chunk để xử lý dữ liệu lớn

Khi cần duyệt qua hàng triệu bản ghi, chunk() sẽ tải dữ liệu theo từng phần, giảm tiêu thụ bộ nhớ.

App\Models\Order::where('status', 'pending')
    ->chunk(500, function ($orders) {
        foreach ($orders as $order) {
            // Xử lý đơn hàng
        }
    });

4. Caching kết quả truy vấn

Laravel Cache có thể lưu trữ kết quả truy vấn trong Redis hoặc file, giảm số lần truy vấn tới DB.

$popularPosts = Cache::remember('popular_posts', 600, function () {
    return App\Models\Post::withCount('comments')
        ->orderBy('comments_count', 'desc')
        ->take(10)
        ->get();
});

5. Sử dụng Raw Expressions khi cần

Đôi khi các hàm Eloquent không đáp ứng yêu cầu tính toán phức tạp. selectRaw() cho phép viết SQL thuần.

$sales = App\Models\Sale::selectRaw('product_id, SUM(amount) as total')
    ->groupBy('product_id')
    ->orderBy('total', 'desc')
    ->get();

6. Indexing và tối ưu schema

Đảm bảo các cột được dùng trong where, joinorderBy có index. Sử dụng migration để thêm index:

Schema::table('orders', function (Blueprint $table) {
    $table->index('status');
    $table->index(['user_id', 'created_at']);
});

Kết luận

Áp dụng các kỹ thuật trên sẽ giúp giảm đáng kể thời gian thực thi truy vấn Eloquent, cải thiện trải nghiệm người dùng và tối ưu tài nguyên server. Đối với những người mới bắt đầu hoặc muốn nâng cao kỹ năng Laravel, việc học các phương pháp tối ưu này là nền tảng quan trọng.

Để nắm vững toàn bộ quy trình phát triển ứng dụng Laravel từ cơ bản tới nâng cao, Tham khảo khóa học "Lập trình web PHP & MySQL với Laravel Framework" tại đây.