Lecții din modul (4/4)
Problema N+1
În dezvoltarea backend, una dintre cele mai frecvente greșeli care limitează catastrofal performanța API este infama problemă „N + 1 Queries”.
De obicei, se strecoară în necunoscut dezvoltatorului care utilizează abstracții de bibliotecă, cum ar fi „ORM-uri” (Object-Relational Mappers: de exemplu, Prisma sau Sequelize) pentru a vorbi cu baza de date din Node.js.
Anatomia dezastrului
Imaginați-vă că o aplicație dorește să returneze întreaga pagină de pornire a comerțului electronic: Toate produsele împreună cu șirul numelui categoriei din care aparține fiecare. Văzut din partea Node.js, un programator fără experiență ar scrie bucla iterativă:
products = await db.query("SELECT * FROM products");(O operațiune mare și voluminoasă 1)- Dezvoltatorul iterează (
for..of) peste fiecareproductdin matricea de 100 găsite - La fiecare pas, în Node.js ei așteaptă o sub-interogare iterativă
categoryName = await db.query("SELECT name FROM categories WHERE id = " + product.category_id);și o încorporează în rezultat (N iterații secundare de interogări lente, mici!)
Total de solicitări către demonul Postgres: 1 + 100 de iterații locale = 101 călătorii dus-întors în microrețea între Node.js și DB. 101 călătorii dus-întors provoacă o supraîncărcare îngrozitoare a rețelei și o latență urâtă. La scară reală, N ar putea să nu fie 100, ci 10.000 de rânduri de facturi totale de explorat! API-ul nu va reveni înainte de a atinge un timeout 5xx.
Răspunsul nativ real: JOIN sau agregare într-o singură interogare
Folosind cu măiestrie abstracțiile DBMS scrise de mână, în loc de comenzi ORM banale în Node, fuzionează execuțiile împreună în milisecunde într-o singură interogare imbatabilă care rezolvă mizeria „N+1”:
SELECT
p.id,
p.name,
c.name AS category_name
FROM products p
JOIN categories c ON p.category_id = c.id;Total călătorii dus-întors API/DB: 1 interogare unică, fuzionată, optimizată matematic de proprii indexuri Postgres, gestionată în întregime cu 0 milisecunde de latență suplimentară a rețelei.
Alternativă de agregare JSON
Versiunile moderne Postgres vă permit chiar să returnați întreaga unire complexă imbricată ca JSON cu json_agg, permițând JavaScript-ului dvs. să primească matricea products, inclusiv sub-matricea lor de recenzii formatate, fără adeziv script local! (În căile și provocările avansate veți studia clauza JSONb a Postgres.)
Rândul tău
Să rezolvăm o adevărată problemă N+1 în curs.\nNode ar fi rulat o selecție globală și apoi ar fi repetat peste fiecare client pentru a-și găsi numele dacă ar fi vrut o recapitulare a comenzilor expediate în această dimineață.\nRezolvați-o prin imprimarea într-o singură fotografie nativă a JOIN între „clienți” (folosește aliasul textual original „c”) și câmpul „comenzi extrase” (câmpul „extras2”). (forțând prefixarea aliasului formal): „c.first_name” (de la client) și „o.status” (din comanda în așteptare).
Afișează indiciu
Sintaxă: SELECT c.first_name, o.status FROM customers c JOIN orders o ON c.id = o.customer_id;
Soluție disponibilă după 3 încercări
Explorarea eficienței GROUP BY
Dacă Group-By-urile logice nu sunt utilizate în baza de date pentru a obține numărul total pe rând și categorie, Node.js va apela DB la nesfârșit, explodând în N+1.\nScrieți o singură interogare care selectează câmpul „oraș” din „clienți” și standardul Postgres numără „COUNT(id)” folosind cuvântul cheie terminal pentru a le agrega unic după nume.
Afișează indiciu
Un banal: SELECT oraș, COUNT(id) FROM clienți GROUP BY oraș;
Soluție disponibilă după 3 încercări