মূল কন্টেন্টে যান
মডিউল 10 · 4-এর পাঠ 4কোর্সে 40/57~12 min
মডিউল পাঠ (4/4)

N+1 সমস্যা

ব্যাকএন্ড ডেভেলপমেন্টে, সবচেয়ে ঘন ঘন ভুলগুলির মধ্যে একটি যা বিপর্যয়করভাবে API কার্যকারিতাকে ট্যাঙ্ক করে তা হল কুখ্যাত "N + 1 Query" সমস্যা।

এটি সাধারণত ডেভেলপারের কাছে অজানা থাকে যারা 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); এর জন্য অপেক্ষা করে এবং এটিকে ফলাফলে এম্বেড করে (N ধীর, ছোট প্রশ্নগুলির মাধ্যমিক পুনরাবৃত্তি!)

পোস্টগ্রেস ডেমনে মোট অনুরোধ: 1 + 100 স্থানীয় পুনরাবৃত্তি = 101 মাইক্রো নেটওয়ার্ক রাউন্ড ট্রিপ Node.js এবং DB এর মধ্যে। 101 রাউন্ড ট্রিপ ভয়ঙ্কর নেটওয়ার্ক ওভারহেড এবং কুৎসিত লেটেন্সি কারণ. বাস্তব স্কেলে, N 100 নাও হতে পারে কিন্তু অন্বেষণ করার জন্য মোট চালানের 10,000 সারি! API একটি 5xx টাইমআউট আঘাত করার আগে ফিরে আসবে না।

আসল নেটিভ উত্তর: একক প্রশ্নে যোগ দিন বা একত্রিত করুন

নোডে তুচ্ছ ওআরএম কমান্ডের পরিবর্তে হাতে লেখা ডিবিএমএস অ্যাবস্ট্র্যাকশনগুলি দক্ষতার সাথে ব্যবহার করে, একটি একক, অপরাজেয় ক্যোয়ারীতে মিলিসেকেন্ডে একত্রে এক্সিকিউশনগুলিকে ফিউজ করে যা "N+1" গোলমালের সমাধান করে:

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

মোট API/DB রাউন্ড ট্রিপ: 1টি অনন্য ক্যোয়ারী, পোস্টগ্রেসের নিজস্ব সূচী দ্বারা গাণিতিকভাবে অপ্টিমাইজ করা, 0 মিলিসেকেন্ড অতিরিক্ত নেটওয়ার্ক লেটেন্সি সহ সম্পূর্ণরূপে পরিচালনা করা হয়েছে।

JSON সমষ্টি বিকল্প

আধুনিক পোস্টগ্রেস সংস্করণগুলি এমনকি আপনাকে json_agg এর সাথে JSON হিসাবে নেস্ট করা পুরো কমপ্লেক্সটি ফেরত দিতে দেয়, যা আপনার জাভাস্ক্রিপ্টকে products অ্যারে প্রাপ্ত করার অনুমতি দেয় যাতে কোনো স্থানীয় স্ক্রিপ্ট আঠা ছাড়াই তাদের ফর্ম্যাট করা পর্যালোচনাগুলির সাব-অ্যারে সহ! (উন্নত পথ এবং চ্যালেঞ্জগুলিতে আপনি পোস্টগ্রেসের JSONb ধারা অধ্যয়ন করবেন।)

তোমার পালা

ব্যায়াম#sql.m10.l4.e1
প্রচেষ্টা: 0লোড হচ্ছে...

আসুন একটি বাস্তব N+1 সমস্যার সমাধান করি৷\nনোড একটি গ্লোবাল সিলেক্ট চালাত এবং তারপরে প্রতিটি গ্রাহকের নাম খুঁজে বের করার জন্য পুনরাবৃত্ত করা যেত যদি এটি আজ সকালে পাঠানো অর্ডারগুলির সংক্ষিপ্ত বিবরণ চায়৷\nআমাকে একটি একক নেটিভ শটে প্রিন্ট করে 'গ্রাহকদের' মধ্যে যোগদান করুন (মূল পাঠ্য উপনাম 'c' ট্র্যাক্ট 'c' এবং 'আলি' ব্যবহার করুন)\n)। তুচ্ছ ক্ষেত্র (আনুষ্ঠানিক উপসর্গ প্রিফিক্সিং জোর করে): 'c.first_name' (গ্রাহকের কাছ থেকে) এবং 'o.status' (মুলতুবি অর্ডার থেকে)।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

সিনট্যাক্স: সিলেক্ট করুন c.first_name, o.status from customers c Join orders o on c.id = o.customer_id;

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

দক্ষতা দ্বারা GROUP অন্বেষণ

ব্যায়াম#sql.m10.l4.e2
প্রচেষ্টা: 0লোড হচ্ছে...

যদি লজিক্যাল Group-Bys ডাটাবেসের মধ্যে ব্যবহার না করা হয় প্রতি সারি এবং বিভাগ প্রতি মোট গণনা পেতে, Node.js অবিরামভাবে DB-কে কল করবে, N+1 এ উড়িয়ে দেবে।\nএকটি একক প্রশ্ন লিখুন যেটি 'গ্রাহক' থেকে 'শহর' ক্ষেত্র নির্বাচন করে এবং স্ট্যান্ডার্ড পোস্টগ্রেস গণনা 'COUNT(আইডি)' টার্মিনাল কী-ওয়ার্ড ব্যবহার করে একটি অনন্য নাম ব্যবহার করে।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

একটি তুচ্ছ: শহর নির্বাচন করুন, গ্রাহকদের থেকে কাউন্ট(আইডি) শহর অনুসারে গ্রুপ করুন;

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ