Modül dersleri (4/4)
N+1 problemi
Arka uç geliştirmede, API performansını felaket derecede düşüren en sık yapılan hatalardan biri, meşhur "N + 1 Sorgu" sorunudur.
Node.js'den veritabanıyla konuşmak için "ORM'ler" (Nesne-İlişkisel Eşleyiciler: örneğin Prisma veya Sequelize) gibi kitaplık soyutlamalarını kullanan geliştirici genellikle bilinmeyen bir şekilde ortaya çıkar.
Felaketin Anatomisi
Bir uygulamanın, e-ticaret ana sayfa listesinin tamamını döndürmek istediğini düşünün: Tüm ürünler, her birinin ait olduğu kategori adı dizesiyle birlikte. Node.js tarafından bakıldığında deneyimsiz bir programcının yinelemeli döngüyü yazması gerekir:
products = await db.query("SELECT * FROM products");(Büyük, hantal bir işlem 1)- Geliştirici, bulunan 100 dizisindeki her
productüzerinde yineleme yapar (for..of) - Her adımda, Node.js'de yinelemeli bir alt sorgu
categoryName = await db.query("SELECT name FROM categories WHERE id = " + product.category_id);beklerler ve bunu sonuca yerleştirirler (N yavaş, küçük sorguların ikincil yinelemeleri!)
Postgres arka plan programına yapılan toplam istek: 1 + 100 yerel yineleme = 101 Node.js ile veritabanı arasında mikro ağ gidiş-dönüşleri. 101 gidiş-dönüş, korkunç ağ yüküne ve çirkin gecikmelere neden olur. Gerçek ölçekte N, keşfedilecek toplam faturanın 100 değil 10.000 satırı olabilir! API, 5xx zaman aşımına uğramadan geri dönmez.
Gerçek Yerel Cevap: Tek Bir Sorguda KATILMA veya Toplama
Node'daki önemsiz ORM komutları yerine elle yazılan DBMS soyutlamalarının ustaca kullanılması, yürütmeleri "N+1" karmaşasını çözen tek, rakipsiz bir sorguda milisaniyeler içinde birleştirir:
SELECT
p.id,
p.name,
c.name AS category_name
FROM products p
JOIN categories c ON p.category_id = c.id;Toplam API/DB gidiş dönüşleri: Postgres'in kendi dizinleri tarafından matematiksel olarak optimize edilmiş, birleştirilmiş ve tamamen 0 milisaniye ekstra ağ gecikmesiyle işlenen 1 benzersiz sorgu.
JSON toplama alternatifi
Modern Postgres sürümleri, tüm karmaşık birleştirmeyi json_agg ile JSON olarak yuvalanmış olarak döndürmenize olanak tanıyarak, JavaScript'inizin herhangi bir yerel komut dosyası yapıştırıcısı olmadan biçimlendirilmiş incelemelerin alt dizisini içeren products dizisini almasına olanak tanır! (İleri düzey yollarda ve zorluklarda Postgres'in JSONb maddesini inceleyeceksiniz.)
Sıra sende
Haydi, yapım aşamasındaki gerçek bir N+1 Sorununu çözelim.\nDüğüm, bu sabah gönderilen siparişlerin özetini istiyorsa genel bir Seçim çalıştırır ve ardından her müşterinin adını bulmak için yinelerdi.\nBana tek bir yerel çekimde 'müşteriler' (orijinal metinsel takma ad 'c'yi kullanın) ve 'siparişler' (takma ad 'o') arasında bir JOIN yazdırarak bunu çözün.\n2 önemsiz alanı çıkarın (resmi takma ad önekini zorlayarak): 'c.first_name' (müşteriden) ve 'o.status' (bekleyen siparişten).
İpucu göster
Sözdizimi: Müşterilerden SELECT c.first_name, o.status c JOIN siparişleri o ON c.id = o.customer_id;
3 denemeden sonra çözüm mevcut
GROUP BY verimliliğini keşfetme
Veritabanında satır ve kategori başına toplam sayıyı elde etmek için mantıksal Group-Bys kullanılmazsa, Node.js DB'yi sonsuza kadar çağırır ve N+1'e ulaşır.\nBunları ada göre benzersiz bir şekilde toplamak için terminal anahtar sözcüğünü kullanarak 'müşteriler'den 'şehir' alanını ve standart Postgres sayımı 'COUNT(id)'yi seçen tek bir sorgu yazın.
İpucu göster
Önemsiz bir şey: SELECT city, COUNT(id) FROM MÜŞTERİLER GRUBA GÖRE ŞEHİR;
3 denemeden sonra çözüm mevcut