मुख्य सामग्री पर जाएं
मॉड्यूल 10 · पाठ 4 का 4पाठ्यक्रम में 40/57~12 min
मॉड्यूल पाठ (4/4)

एन+1 समस्या

बैकएंड विकास में, सबसे लगातार गलतियों में से एक जो एपीआई प्रदर्शन को विनाशकारी रूप से ख़राब करती है वह कुख्यात "एन + 1 क्वेरीज़" समस्या है।

यह आमतौर पर उस डेवलपर को पता नहीं चलता है जो Node.js से डेटाबेस से बात करने के लिए "ORMs" (ऑब्जेक्ट-रिलेशनल मैपर्स: जैसे प्रिज्मा या सीक्वेलाइज़) जैसे लाइब्रेरी एब्स्ट्रैक्शन का उपयोग कर रहा है।

आपदा की शारीरिक रचना

कल्पना कीजिए कि कोई ऐप संपूर्ण ई-कॉमर्स होमपेज सूची वापस करना चाहता है: सभी उत्पाद, प्रत्येक श्रेणी के नाम की स्ट्रिंग सहित। Node.js की ओर से देखने पर, एक अनुभवहीन प्रोग्रामर पुनरावृत्त लूप लिखेगा:

  1. products = await db.query("SELECT * FROM products"); (एक बड़ा, भारी ऑपरेशन 1)
  2. डेवलपर 100 की सरणी में प्रत्येक product पर (for..of) पुनरावृत्त करता है
  3. प्रत्येक चरण पर, Node.js में वे एक पुनरावृत्त उप-क्वेरी categoryName = await db.query("SELECT name FROM categories WHERE id = " + product.category_id); की प्रतीक्षा करते हैं और इसे परिणाम में एम्बेड करते हैं (धीमी, छोटी क्वेरी के द्वितीयक पुनरावृत्ति!)

पोस्टग्रेज डेमॉन के लिए कुल अनुरोध: 1 + 100 स्थानीय पुनरावृत्तियाँ = 101 नोड.जेएस और डीबी के बीच माइक्रो नेटवर्क राउंड ट्रिप। 101 राउंड ट्रिप के कारण भयानक नेटवर्क ओवरहेड और बदसूरत विलंबता होती है। वास्तविक पैमाने पर, तलाशने के लिए कुल चालानों की 100 नहीं बल्कि 10,000 पंक्तियाँ हो सकती हैं! एपीआई 5xx टाइमआउट से पहले वापस नहीं आएगा।

वास्तविक मूल उत्तर: एकल प्रश्न में शामिल हों या एकत्रीकरण

नोड में तुच्छ ओआरएम कमांड के बजाय हाथ से लिखे गए डीबीएमएस एब्स्ट्रैक्शन का कुशलतापूर्वक उपयोग, निष्पादन को एक एकल, अपराजेय क्वेरी में मिलीसेकंड में एक साथ जोड़ता है जो "एन + 1" गड़बड़ी को हल करता है:

SQL
SELECT
  p.id,
  p.name,
  c.name AS category_name
FROM products p
JOIN categories c ON p.category_id = c.id;

कुल एपीआई/डीबी राउंड ट्रिप: 1 अद्वितीय क्वेरी, फ़्यूज्ड, गणितीय रूप से पोस्टग्रेज़ के स्वयं के इंडेक्स द्वारा अनुकूलित, पूरी तरह से 0 मिलीसेकंड अतिरिक्त नेटवर्क विलंबता के साथ नियंत्रित किया जाता है।

JSON एकत्रीकरण विकल्प

आधुनिक पोस्टग्रेज़ संस्करण आपको json_agg के साथ JSON के रूप में नेस्टेड पूरे कॉम्प्लेक्स को वापस करने की सुविधा भी देते हैं, जिससे आपके जावास्क्रिप्ट को बिना किसी स्थानीय स्क्रिप्ट गोंद के स्वरूपित समीक्षाओं की उनकी उप-सरणी सहित products सरणी प्राप्त करने की अनुमति मिलती है! (उन्नत पथों और चुनौतियों में आप पोस्टग्रेज के JSONb क्लॉज का अध्ययन करेंगे।)

आपकी बारी

व्यायाम#sql.m10.l4.e1
प्रयास: 0लोड हो रहा है...

आइए निर्माण में एक वास्तविक एन + 1 समस्या को हल करें। 'c.first_name' (ग्राहक से) और 'o.status' (लंबित ऑर्डर से)।

संपादक लोड हो रहा है...
संकेत दिखाएँ

सिंटैक्स: ग्राहकों से c.first_name, o.status चुनें c ऑर्डर में शामिल हों o ON c.id = o.customer_id;

3 प्रयासों के बाद समाधान उपलब्ध है

दक्षता के आधार पर समूह की खोज

व्यायाम#sql.m10.l4.e2
प्रयास: 0लोड हो रहा है...

यदि प्रति पंक्ति और श्रेणी की कुल गिनती प्राप्त करने के लिए डेटाबेस के अंदर तार्किक ग्रुप-बाय का उपयोग नहीं किया जाता है, तो Node.js DB को अंतहीन रूप से कॉल करेगा, जो N+1 में बदल जाएगा।\nएक एकल क्वेरी लिखें जो 'ग्राहकों' से 'शहर' फ़ील्ड का चयन करती है और टर्मिनल कीवर्ड का उपयोग करके मानक पोस्टग्रेज गिनती 'COUNT(id)' को नाम से विशिष्ट रूप से एकत्रित करती है।

संपादक लोड हो रहा है...
संकेत दिखाएँ

एक तुच्छ बात: शहर का चयन करें, ग्राहकों के समूह से शहर के अनुसार गिनती (आईडी) करें;

3 प्रयासों के बाद समाधान उपलब्ध है