MongoDB Academy · درس

تقاطع الفهارس مقابل الفهارس المركبة

سيفهم المتعلمون متى يدمج MongoDB عدة فهارس أحادية الحقل، ومتى يتفوق الفهرس المركب على التقاطع.

الدرس 3 من 413 خطوة

تقاطع الفهارس مقابل الفهارس المركبة درس مجاني في MongoDB Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في MongoDB Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة MongoDB Academy 4 دروس في المجموع.

ما هو تقاطع الفهارس؟

تقاطع الفهارس هو قدرة MongoDB على استخدام فهرسين أحاديي الحقل أو أكثر في الوقت نفسه لتلبية استعلام واحد. فبدلًا من إنشاء فهرس مركب يغطي جميع حقول التصفية، يفحص MongoDB عدة فهارس بشكل مستقل، ثم يأخذ تقاطع معرّفات المستندات المطابقة لها. قد يبدو ذلك مريحًا، لكنه نادرًا ما يكون سريعًا مثل الفهرس المركب المصمم جيدًا.

كيف يعمل تقاطع الفهارس داخليًا

عندما يدرس MongoDB تقاطع الفهارس، ينفّذ مخطط الاستعلام ما يلي: 1) يفحص الفهرس A بحثًا عن المستندات المطابقة للشرط 1، ويجمع معرّفات سجلاتها. 2) يفحص الفهرس B بحثًا عن المستندات المطابقة للشرط 2. 3) يحسب تقاطع مجموعتي المعرّفات. 4) يجلب المستندات الفعلية باستخدام تلك المعرّفات. ويُسمى ذلك مرحلة AND_SORTED أو AND_HASH في مخرجات explain().

// With two single-field indexes:
db.orders.createIndex({ status: 1 })
db.orders.createIndex({ customerId: 1 })

// Query may intersect both indexes
db.orders.find({ status: 'pending', customerId: 'c001' })
  .explain('executionStats')
// Look for 'AND_SORTED' or 'AND_HASH' stage in winningPlan

متى يختار MongoDB التقاطع

لا يستخدم MongoDB تقاطع الفهارس إلا عندما يحسب مخطط الاستعلام أنه أقل تكلفة من البدائل. ويشغّل المخطط ما يصل إلى 200 خطة مرشحة بالتوازي، باستخدام التنفيذ التجريبي، ثم يختار الخطة ذات أقل تكلفة تقديرية. ويزداد احتمال اختيار التقاطع عندما تكون المجموعة كبيرة ويكون كل فهرس منفرد عالي الانتقائية، إذ يضيّق كلاهما مجموعة المرشحين بدرجة كبيرة قبل خطوة التقاطع.

// Check if MongoDB chose to intersect indexes
const plan = db.orders.find({
  status: 'pending',
  customerId: 'c001'
}).explain('executionStats')

// Intersection chosen:
print(JSON.stringify(plan.queryPlanner.winningPlan, null, 2))
// Look for: 'stage': 'AND_SORTED'

الفهرس المركب مقابل التقاطع: الفرق الأساسي

يخزّن الفهرس المركب مفاتيح من عدة حقول في شجرة B واحدة مرتبة مسبقًا. ويُجري الاستعلام على تلك الحقول فحصًا واحدًا فعالًا للفهرس، ويُرجع المستندات بترتيبها. أما تقاطع الفهارس فيُجري عدة عمليات فحص منفصلة، ثم يدمج النتائج في الذاكرة. وتضيف خطوة الدمج عبئًا على المعالج والذاكرة يتجنبه الفهرس المركب بالكامل.

// Compound index: one scan, sorted output
db.orders.createIndex({ status: 1, customerId: 1 })

// Single scan: fast, no in-memory merge
db.orders.find({ status: 'pending', customerId: 'c001' })
// explain(): IXSCAN stage only — no AND_SORTED

تتفوق الفهارس المركبة في الترتيب

لا يستطيع تقاطع الفهارس تلبية الترتيب، إذ لا تكون مجموعة النتائج المدمجة مرتبة وفق مفتاح الترتيب، ولذلك يجب على MongoDB تنفيذ مرحلة SORT في الذاكرة. أما الفهرس المركب الذي يتضمن حقل الترتيب، فيعرض النتائج بالترتيب مباشرةً من الفهرس، متجنبًا عبء الترتيب بالكامل. وبالنسبة إلى الاستعلامات التي تجري التصفية والترتيب معًا، يتفوق الفهرس المركب تقريبًا دائمًا.

// Index intersection + sort = in-memory sort required
db.orders.find({ status: 'pending', customerId: 'c001' })
  .sort({ createdAt: 1 })
// Even if both status and customerId indexes intersect,
// MongoDB must still sort the merged result in memory

// Compound index avoids the sort stage
db.orders.createIndex({ status: 1, customerId: 1, createdAt: 1 })

متى يمكن للتقاطع أن يتفوق على الفهرس المركب

يتفوق تقاطع الفهارس أحيانًا على الفهرس المركب عندما: 1) يكون كلا الفهرسين المنفردين عالي الانتقائية، بحيث يُرجع كل منهما عددًا قليلًا جدًا من المستندات. 2) يكون الاستعلام مخصصًا وغير متكرر، فلا يمكن التنبؤ بالحقول التي ستُستخدم معًا، ويصبح إنشاء فهرس مركب لكل تركيبة أمرًا غير عملي. 3) تكون المجموعة كثيفة الكتابة، إذ يعني تقليل عدد الفهارس خفض عبء الكتابة، وبالتالي يتيح استخدام التقاطع بين فهرسين موجودين تجنب إضافة فهرس ثالث.

التحكم في مخطط الاستعلام باستخدام hint()

يمكنك إجبار MongoDB على استخدام فهرس محدد، أو استراتيجية تقاطع محددة، باستخدام .hint(). ويتجاوز ذلك الاختيار التلقائي لمخطط الاستعلام، ويفيد في المقارنة المعيارية، إذ يمكنك مقارنة إحصاءات التنفيذ للفهرس المركب الذي اخترته يدويًا بما سينفذه المخطط باستخدام الفهارس المنفردة.

// Force a specific compound index
db.orders.find({ status: 'pending', customerId: 'c001' })
  .hint({ status: 1, customerId: 1 })
  .explain('executionStats')

// Force use of a single-field index (no intersection)
db.orders.find({ status: 'pending', customerId: 'c001' })
  .hint({ status: 1 })
  .explain('executionStats')

اكتشاف التقاطع في مخرجات explain()

عندما يستخدم MongoDB تقاطع الفهارس، تعرض مخرجات explain() مرحلة AND_SORTED أو AND_HASH باعتبارها المرحلة الأصلية لمرحلتَي IXSCAN. تُستخدم AND_SORTED عندما يُرجع كلا الفهرسين النتائج بالترتيب نفسه، بينما تنشئ AND_HASH تجزئة في الذاكرة لإحدى مجموعتي النتائج، ثم تبحث فيها باستخدام المجموعة الأخرى. وتشير كلتاهما إلى أن الفهرس المركب المختار جيدًا قد يكون أسرع.

// Identify intersection usage
const plan = db.orders
  .find({ status: 'pending', region: 'EU' })
  .explain('executionStats')

// Check for AND_SORTED or AND_HASH
// If found, benchmark against a compound index { status:1, region:1 }

القاعدة العامة: تفضيل الفهارس المركبة

بالنسبة إلى أنماط الاستعلام المعروفة والمتكررة، يكون الفهرس المركب أسرع تقريبًا دائمًا من الاعتماد على التقاطع. والسببان الوحيدان لتفضيل التقاطع هما: أن تكون الاستعلامات غير متوقعة بدرجة تمنع تغطيتها بفهرس مركب، أو أن يكون معدل الكتابة مرتفعًا جدًا بحيث تصبح إضافة مزيد من الفهارس مكلفة للغاية. في هذه الحالات، أبقِ الفهارس المنفردة بسيطة، ودَع المخطط يجري التقاطع عندما يكون ذلك مفيدًا.

مراجعة الفهارس: إزالة الفهارس الزائدة

مع تطور التطبيقات، يضيف المطورون الفهارس بشكل تفاعلي. وبمرور الوقت، تتراكم في المجموعات فهارس زائدة تؤدي إلى إبطاء عمليات الكتابة من دون فائدة لعمليات القراءة. راجع الفهارس بانتظام باستخدام $indexStats: فأي فهرس تبلغ قيمة accesses.ops فيه صفرًا لفترة طويلة يكون غير مستخدم ويمكن حذفه. وابحث أيضًا عن الفهارس التي أصبحت زائدة بسبب قاعدة بادئة الفهرس المركب.

// Identify unused indexes
db.orders.aggregate([{ $indexStats: {} }])
// { name: 'status_1', accesses: { ops: 0, since: ... } }
// If ops is 0 since a long time, the index is unused — drop it

db.orders.dropIndex('status_1')

إرشادات عملية: إطار لاتخاذ القرار

استخدم إطار العمل التالي: هل نمط الاستعلام معروف ومتكرر؟ ← أنشئ فهرسًا مركبًا باستخدام ESR. هل الاستعلام مخصص أو يصعب التنبؤ به؟ ← اعتمد على الفهارس المنفردة وتقبّل احتمال حدوث التقاطع. هل معدل الكتابة بالغ الأهمية؟ ← قلّل العدد الإجمالي للفهرسة، واحذف الفهارس غير المستخدمة. هل يتضمن الاستعلام ترتيبًا؟ ← استخدم دائمًا فهرسًا مركبًا؛ فتقاطع الفهارس لا يلبي عمليات الترتيب مطلقًا.

تحقق سريع

اختبر مدى فهمك لمفاهيم MongoDB وقواعد بيانات NoSQL الواردة في هذا الدرس.

مراجعة الدرس

في هذا الدرس تعلّمت: يستخدم تقاطع الفهارس فهرسين أحاديي الحقل ويدمج نتائجهما في الذاكرة، مما يضيف عبئًا إضافيًا، وتكون الفهارس المركبة أسرع تقريبًا دائمًا لأنماط الاستعلام المعروفة والمتكررة — وخصوصًا الاستعلامات التي تتضمن عمليات فرز، واستخدم $indexStats للعثور على الفهارس غير المستخدمة أو الزائدة وإزالتها، لأنها تؤدي إلى إبطاء عمليات الكتابة. بعد ذلك سنستكشف نصائح لتحسين أداء مسارات التجميع.

البدء مجانًا

تعلم JavaScript مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
30
الدروس
120

الأسئلة الشائعة

هل درس «تقاطع الفهارس مقابل الفهارس المركبة» مجاني؟

نعم — نص درس «تقاطع الفهارس مقابل الفهارس المركبة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة MongoDB Academy، انتقل إلى CoddyKit PRO. تتضمن دورة MongoDB Academy 4 دروس في المجموع.

ماذا ستتعلم في «تقاطع الفهارس مقابل الفهارس المركبة»؟

سيفهم المتعلمون متى يدمج MongoDB عدة فهارس أحادية الحقل، ومتى يتفوق الفهرس المركب على التقاطع. تتمرن على MongoDB Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ MongoDB Academy؟

لا تُشترط خبرة سابقة. MongoDB Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «تقاطع الفهارس مقابل الفهارس المركبة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس MongoDB Academy هذا؟

نعم. كل درس في MongoDB Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. محلّل قاعدة البيانات وسجل الاستعلامات البطيئة
  2. قاعدة بادئة الفهرس المركب ومبدأ ESR
  3. تقاطع الفهارس مقابل الفهارس المركبة
  4. نصائح لتحسين مسار التجميع
← العودة إلى MongoDB Academy