N+1 là bug hiệu năng kinh điển của ORM: bạn query một lần lấy N item (1 query), rồi lặp qua từng item để lấy dữ liệu liên quan (thêm N query) → tổng N+1 query thay vì 1-2. Ví dụ: lấy 100 user rồi lấy bài viết của từng người = 101 query.
Cách phát hiện: bật log query trong Prisma — new PrismaClient({ log: ['query'] }) — rồi đếm số query mỗi request.
Cách xử lý trong Prisma:
- include (eager load): prisma.user.findMany({ include: { posts: true } }) — Prisma chỉ chạy ~2 query rồi tự ghép.
- Dùng select lồng nhau để lấy đúng field cần.
- Tránh gọi lazy load (user.posts()) bên trong vòng lặp.
Với GraphQL: dùng DataLoader — gom nhiều lượt load lẻ trong cùng một tick thành một query batch. Prisma chưa có sẵn DataLoader nhưng có thể dùng @paljs/plugins hoặc tự viết.
N+1 is the classic ORM performance bug: you query once to get N items (1 query), then loop over each to fetch related data (N more queries) → N+1 queries total instead of 1-2. Example: fetch 100 users then each user's posts = 101 queries.
How to detect: enable query logging in Prisma — new PrismaClient({ log: ['query'] }) — then count queries per request.
How to fix in Prisma:
- include (eager load): prisma.user.findMany({ include: { posts: true } }) — Prisma runs ~2 queries and merges them.
- Use nested select to fetch only the fields you need.
- Avoid lazy loads (user.posts()) inside loops.
With GraphQL: use DataLoader — it batches many individual loads within one tick into a single query. Prisma has no built-in DataLoader, but you can use @paljs/plugins or write your own.