N + 1 Problem

Tham khảo : https://viblo.asia/p/n-1-query-tinh-nang-hay-la-bug-maGK7WnMKj2

1. N + 1 Problem là gì ?

N + 1 Problem là một quá trình thực hiện N + 1 câu truy vấn đến cơ sở dữ liệu.

Hãy xét một ví dụ sau đây để thấy rõ :

Ví dụ: có hai quan hệ là book(id, name, author_id) user(id, name) có quan hệ one-to-many với nhau tức là một người có thể viết nhiều sách. Yêu cầu truy xuất thông tin của các cuốn sách theo dạng JSON như sau: book { id name author { id name } }

Để thực hiện được cái này thông thường ta thực hiện câu truy vấn như sau :

BOOKS.all.each do 
    Book.user
end

Các câu lệnh sinh ra sẽ là :

SELECT "book".* from BOOKS

SELECT "author".* from USERS where "USERS".id = ?
SELECT "author".* from USERS where "USERS".id = ?
SELECT "author".* from USERS where "USERS".id = ?   

Như vậy ta có thể thấy nó bao gồm hai giai đoạn : - Giai đoạn 1: Chọn các cuốn sách từ sách - Giai đoạn 2: Tìm các tác giả cho các cuốn sách đó Giả sử có N = 3 quyển sách thì sẽ có bao nhiêu câu truy vấn ? Đáp án là 4 1 câu truy vấn cho giai đoạn 1 và 3 câu truy vấn giai đoạn 2. Như vậy N = 3 thì cần N + 1 câu truy vấn do đó bài toán này được gọi là N + 1 Problem

Đối với table có kích thước lớn chằng hạn như 1 000 000 thì số lượng câu truy vấn cần thực hiện sẽ là 1 000 001 như vậy sẽ ảnh hưởng rất lớn đến performance

Vậy làm thế nào để khắc phục vấn đề này ?

2. Cách giải quyết N + 1 Problem

2.1 Sử dụng Select in() query

SELECT "books".* FROM "BOOKS"
SELECT "authors".* FROM "USERS" WHERE "books"."author_id" IN (1, 2, 3)

Chỉ cần 2 bước đơn giản đầu tiên là truy vấn toàn bộ sách sau đó load các tác giả tương ứng.

2.2 Sử dụng Join

SELECT "books".* FROM "BOOKS" INNER JOIN "USERS" ON BOOKS.Author_id = USER.id

Như vậy Join chỉ tốn có 1 query mà thôi

Các loại JOIN

Các loại JOIN

2.3 Vậy nên lựa chọn loại nào ?

Last updated

Was this helpful?