Пошук уроків, статей та іншого контенту
Класична проблема продуктивності ORM — один запит перетворюється на сотні.
N+1 — поширена проблема продуктивності: код робить 1 запит, щоб отримати список із N записів, а потім ще N окремих запитів, щоб отримати пов'язані дані для кожного запису — разом N+1 запитів замість одного чи двох.
// 1 запит: отримати всі пости
const posts = await prisma.post.findMany();
// Потім N запитів — по одному на кожен пост!
for (const post of posts) {
post.author = await prisma.user.findUnique({ where: { id: post.authorId } });
}
// Для 100 постів це 101 запит до бази даних замість 1-2Проблема часто непомітна на етапі розробки з невеликою тестовою базою (10 записів — 11 запитів, різниця несуттєва), але стає критичною в продакшені з тисячами записів — і виявляється вже під навантаженням.
Замість окремих запитів у циклі, попросити ORM одразу підвантажити пов'язані дані одним запитом із JOIN:
const posts = await prisma.post.findMany({
include: { author: true }, // Prisma сам робить ефективний JOIN або batched-запит
});
// 1 запит замість N+1Коли пов'язані дані потрібно завантажити з іншого джерела (наприклад, окремий мікросервіс, а не та сама база даних), пряме включення в JOIN неможливе — тоді використовують патерн DataLoader: замість запиту на кожен окремий id, всі id, потрібні за один «тік» подієвого циклу, збираються й запитуються одним батч-викликом.
Увімкнути логування SQL-запитів у розробці (більшість ORM це підтримують) і подивитись, скільки запитів реально виконується на один запит сторінки.
Різке уповільнення сторінки, що показує список, пропорційно кількості елементів у списку — класична ознака.
Профілювання запитів у продакшн-моніторингу (APM-інструменти показують кількість запитів на HTTP-запит).
N+1 виникає, коли код завантажує пов'язані дані окремим запитом для кожного елемента списку замість одного пакетного запиту. Eager loading (JOIN/include) — рішення за замовчуванням у межах однієї бази даних; DataLoader-подібний батчинг — коли дані приходять з різних джерел. Індекси (окрема стаття) прискорюють кожен окремий запит, але не рятують від того, що запитів у принципі забагато.