N+1 problems
2024-02-26
ưu tiên đẩy truy vấn xuống cho db làm
Khái niệm
Là một truy vấn không hiệu quả vì sử dụng quá nhiều câu truy vấn.
Ví dụ:
# load thông tin 1 list user (1)
User Load: SELECT "users".* FROM "users"
# sau đó sinh ra n câu từ đó (n). -> n+1
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? [["user_id", 1]]
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? [["user_id", 2]] ...
Khắc phục
IN. Chạy 2 câu truy vấn. một câu lấy list từ bảng 1. một câu lấy thông tin liên quan list đó từ bảng 2.
JOIN. Dùng join khi cần tối ưu trong trường hợp có filter trên bảng 2.
Chú ý: k phải lúc nào n+1 cũng xấu. trong trường hợp phân trang cần load ít dữ liệu thôi mà join cả 2 bảng thì hơi căng(lấy có 10 user mà join với hàng triệu bài post để lấy thông tin post của 10 user đó)
Eager Loading
Preload: Initiates two queries, the first to fetch the primary model and the second to fetch associated models.
Eager load: Does a left outer join which initiates one query to fetch both primary and associated models.