توضّح هذه الصفحة ناتج طلب بحث تم تنفيذه باستخدام ميزة "تفسير طلب البحث". لمعرفة كيفية تنفيذ طلب بحث باستخدام ميزة "تفسير طلب البحث"، يُرجى الاطّلاع على مقالة تحليل تنفيذ طلب البحث باستخدام ميزة "تفسير طلب البحث".
المفاهيم الشائعة
يتم استخدام المفاهيم والمصطلحات الشائعة التالية في جميع أنحاء شجرة التنفيذ.
الصفوف والسجلات
يُستخدم المصطلحان صف وسجلّ للإشارة بشكل عام إلى مستند أو إدخال فهرس.
المتغيرات
تشير السمة $ إلى متغيّر يتم إنشاؤه أو
الإشارة إليه في شجرة التنفيذ. على سبيل المثال: $foo_1. تُستخدم هذه المتغيرات عادةً للإشارة إلى محتوى مستند أو قيمة تعبير تم تقييمه أثناء تنفيذ طلب بحث.
يمكن أن تظهر المتغيّرات الداخلية التالية في عُقد التنفيذ:
-
$__key__: المفتاح هو معرّف داخلي لمستند. هذا معرّف فريد ومطلق يتضمّن المشروع وقاعدة البيانات والمسار الكامل للمستند. -
$__id__: المعرّف هو معرّف فريد لمستند ضمن مجموعته. ويكون هذا المعرّف فريدًا ضمن مجموعة واحدة. $rid- رقم تعريف الصف هو معرّف داخلي لمستند في مساحة التخزين. ويكون هذا المعرّف فريدًا ضمن مجموعة واحدة.
لنفترض أنّ عقدة Compute تُستخدَم لاحتساب
__id__ من المستند __key__:
Compute
| $__id__1: _id($__key__)
| records returned: 1
القيود والنطاقات
تستخدم بعض عُقد الفحص السمتَين constraints وranges لوصف نطاق
القيم التي يتم فحصها. تستخدم هذه السمات تنسيق شجرة النطاق الذي
يحتوي على قائمة بالقيم. تتوافق هذه القيم مع القائمة المرتبة للمفاتيح
التي تظهر في تعريف الفهرس. على سبيل المثال، النطاق الأول الذي يظهر في الشجرة، هنا (1..5]، يتوافق مع القيود المفروضة على المفتاح الأول، هنا a، في القائمة المرتبة للمفاتيح:
| index: type=CollectionGroupIndex, id=CICAgOjXh#EK, keys=[a ASC, b ASC, __key__ ASC]
| constraints: /
|----(1..5]
|----[1L]
يشير كل مستوى من مستويات المسافة البادئة إلى القيد الذي ينطبق على المفتاح التالي في
القائمة. تمثّل الأقواس المربعة نطاقًا شاملاً، بينما تمثّل الأقواس المستديرة نطاقًا حصريًا. في هذه الحالة، تتم ترجمة القيد إلى 1 < "a" <= 5 و"b" = 1.
في المثال التالي الذي يتضمّن فروعًا متعددة لـ a،
يتوافق القيد مع 1 < a <= 5 OR a = 10:
| constraints: /
|----(1L, 5L]
|----[10L]
المتغيّرات الرئيسية
في بعض عُقد الفحص (مثل SequentialScan)، تتوفّر قائمة بالمفاتيح كجزء من السمة index، وسمة keys منفصلة في العقدة Scan. تشير السمة keys في العقدة Scan إلى اسم المتغيّر لكل مفتاح في تعريف الفهرس، بالترتيب. يمكن استخدام المتغيّرات للإشارة إلى قيم وقت التشغيل للحقل الذي تم فحصه في أعلى شجرة التنفيذ.
في المثال التالي، يتم ربط قيمة الحقل user للمستند الحالي بالمتغيّر $user_1 وقيمة date_placed بالمتغيّر $date_placed_1.
index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __key__ ASC]
keys: [user ASC, date_placed ASC, __key__ ASC]
عُقد التنفيذ
يمكن أن تحتوي شجرة تنفيذ طلب البحث على العُقد التالية.
SeekingScan
يمثّل هذا الحقل عملية فحص ديناميكية قد لا تكون فيها الصفوف المعروضة ضمن نطاق تسلسلي واحد من الفهرس، ويجب إجراء عمليات فحص متعددة ومختلفة لتلبية طلب البحث.
على سبيل المثال، إذا كان هناك طلب بحث يتضمّن a وb يساوي 1 ويعمل على فهرس ["a" ASC, "b" ASC]، سيحتاج إلى فحص وعرض نطاق منفصل، قد يكون غير متسلسل، لكل قيمة مميزة لـ a.
هذا أكثر كفاءة من TableScan كامل، ولكنه أقل كفاءة من SequentialScan واحد على فهرس مركّب من ["b" ASC, "a" ASC].
• SeekingScan
| constraints: /
|----(-∞..+∞)
|----[1L]
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, quantity ASC, __key__ ASC]
| keys: [user ASC, quantity ASC, __key__ ASC]
| properties: Selection { user }
| records returned: 1
| records scanned: 1
SequentialScan
تمثّل هذه السمة عملية فحص لنطاق ثابت ومتسلسل من الصفوف في مساحة التخزين يمكن إجراؤها في عملية قراءة واحدة.
يشير الرمز key ordering length إلى عدد المفاتيح التي يجب الاحتفاظ بها
وإرجاعها بالترتيب الأصلي للمفاتيح. بالنسبة إلى مخطط [k1, k2, k3]، فإن طول ترتيب المفتاح الذي يساوي 0 يعني أن الفحص يمكن أن يعرض المستندات بأي ترتيب، و1 يعني الترتيب حسب k1، ولكن الصفوف التي لها نفس قيمة k1 يمكن أن تأتي بأي ترتيب، و3 يعرض المستندات بترتيب دقيق.
• SequentialScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| key ordering length: 3
| keys: [user ASC, date_placed ASC, __key__ ASC]
| limit: 10
| properties: Selection { a }
| ranges: /
| records returned: 1
| records scanned: 1
UniqueScan
تمثّل هذه السمة عملية فحص لنطاق ثابت ومتسلسل من الصفوف في مساحة التخزين مع إزالة الصفوف المكرّرة في الذاكرة.
• UniqueScan
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| keys: [user ASC, date_placed ASC, __key__ ASC]
| properties: Selection { a }
| ranges: /
|----(-∞..+∞)
| records returned: 1
| records scanned: 1
IndexSeek
يمثّل هذا الحقل عملية فحص ديناميكية حيث يمكن تحديد معلَمات الصفوف التي يتم عرضها من خلال بيانات وقت التشغيل وقد لا تكون ضمن نطاق تسلسلي واحد للفهرس، وقد يتم إجراء عمليات فحص متعددة ومختلفة لتلبية طلب البحث.
على سبيل المثال، إذا كان طلب البحث الذي يساوي فيه user القيمة $user_id ويساوي فيه date_placed القيمة "2025-08-10" يعمل على فهرس ["user" ASC, "date_placed" ASC]، سيستخدم قيمة المتغيّر $user_id في وقت التشغيل وقيد "2025-08-10" على date_placed لتقييد نطاقات الفحص.
• IndexSeek
| index: type=CollectionGroupIndex, id=CAE, keys=[user ASC, date_placed ASC, __key__ ASC]
| fields: [$user_1 ASC, $date_placed_1 ASC, $rid ASC]
| key: $key_1
| filter: equal($user_1, $user_id) AND equal($date_placed_1, "2025-08-10")
| records returned: 1
| records scanned: 1
جلب
يتم ربط معرّف الصف المقدَّم بمحتوى الصف الفعلي من مساحة التخزين الأساسية. Fetch is required if a parent node (or the final query
result) requires a subset of fields from the documents.
• Fetch
| order: PRESERVE_INPUT_ORDER
| peak memory usage: 4.00 KiB (4,096 B)
| properties: *
| records returned: 1
LookupById
تنفّذ هذه العملية عملية دمج من خلال البحث عن المستندات في مجموعة خارجية حسب معرّفها. ويتم الحصول على أرقام التعريف المطلوب البحث عنها من حقل في مستندات الإدخال. تتم إضافة نتائج البحث كحقل جديد إلى مستندات الإدخال.
• LookupById
| local_field: $localField_1
| foreign_datasource: (default)#/**/foreign
| output: $output_1
TableScan
فحص كامل وغير مرتّب لمجموعة يُستخدَم عند تشغيل طلب بحث بدون فهرس مرتبط.
يمكن أن يكون الترتيب إما STABLE أو UNDEFINED، حيث يشير STABLE إلى
ترتيب حتمي.
• TableScan
| order: STABLE
| properties: *
| records returned: 1
| records scanned: 1
| source: (default)#/**/collection
NestedLoopJoin
تؤدي هذه العملية إلى دمج مجموعتَي بيانات (يسرى ويمنى) من خلال تكرار
كل صف من الإدخال الأيسر، والبحث في الإدخال الأيمن عن الصفوف المطابقة لكل صف أيسر
استنادًا إلى join_condition.
يشير join_type إلى نوع الربط. على سبيل المثال، تعني السمة LEFT_OUTER أنّه يتم تضمين جميع الصفوف من الإدخال الأيمن مرة واحدة على الأقل في الناتج.
إذا لم يتطابق صف في الإدخال الأيسر مع أي صف في الإدخال الأيمن استنادًا إلى
join_condition، سيتم تضمينه مع قيم فارغة
للأعمدة من الإدخال الأيمن.
• NestedLoopJoin
| join_type: LEFT_OUTER
| join_condition: equal($left, $right)
|
└── • left tree
| ...
└── • right tree
...
HashAggregate
تنفيذ العمليات المجمّعة المستندة إلى التجزئة يتطلّب ذلك تجسيد المجموعة الكاملة في الذاكرة قبل عرض النتيجة، ويجب ألا يتجاوز الحدّ الأقصى لذاكرة طلب البحث.
• HashAggregate
| aggregations: [sum($b_1) AS total]
| groups: [$a_1]
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 0
StreamAggregate
عقدة تجميعية متخصصة تحتفظ بالحالة لمجموعة واحدة فقط في كل مرة، مما يقلل من ذروة استخدام الذاكرة. يُستخدَم عندما تُرجع العقدة الفرعية الأساسية المجموعات بشكل تسلسلي. على سبيل المثال، عند التجميع حسب القيم المميزة لحقل ما أثناء استخدام فهرس في ذلك الحقل.
• StreamAggregate
| keys: [foo ASC, bar ASC]
| properties: Selection { baz }
| aggregations: [$sum($foo_1) AS baz]
MajorSort
لتنفيذ عملية ترتيب على مجموعة ثابتة من المواقع الإلكترونية يتم عرض جميع السجلات في الذاكرة مرة واحدة وإرجاع القيم المرتبة بالترتيب، ويكون حجم مجموعة الترتيب محدودًا بحد الذاكرة المسموح به لطلب البحث.
عند توفير حد لاحق، يتم استخدام خوارزمية ترتيب top-k لتقليل استخدام الذاكرة. باستخدام هذه الطريقة، يمكن إجراء عمليات الفرز على مجموعة كبيرة عشوائيًا من السجلات طالما أنّ الذاكرة المستخدمة لتخزين العناصر k التي تم أخذها في الاعتبار لا تتجاوز الحدّ الأقصى.
• MajorSort
| fields: [a ASC, b DESC]
| limit: 10
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 1
Concat
تدمج نتائج عدة عُقد فرعية وتعرض النتيجة للعقدة الرئيسية. لا تزيل هذه العقدة النتائج المكرّرة التي تظهر في عقد فرعية متعددة، وترتيب النتائج المعروضة غير محدّد.
• Concat
├── • Fetch
...
├── • Fetch
الحوسبة
لتقييم مجموعة من التعبيرات، مع تعيين النتائج لمجموعة من المتغيرات.
• Compute
| $user_1: user
| $full_name_1: str_concat($first_name_1, " ", $last_name_1)
| $address_1: UNSET
| records returned: 1
فلتر
تعرض الصفوف بشكل انتقائي إذا كانت تطابق التعبير المقدَّم فقط.
• Filter
| expression: $eq(foo, "bar")
| records returned: 1
RecordCount
يحتسب عدد الصفوف التي تنتجها العقدة الفرعية ويُخرج العدد الحالي إلى المتغيّر المحدّد في السمة count.
• RecordCount
| count: $row_number_1
| records returned: 1
القيم
تنتج سلسلة من القيم الحرفية للعمل عليها. يُستخدم بشكل أساسي عندما يتم تقديم قائمة محدّدة من المستندات كإدخال لطلب بحث.
• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]
Unnest
تُخرج القيمة التي تنتجها العقدة الفرعية من التداخل.
• Unnest
| expression: foo AS unnested_foo
الحدّ
تحدّ من عدد الصفوف التي يتم عرضها للعقدة الرئيسية.
• Limit
| limit: 10
| records returned: 1
الإزاحة
تتخطّى عددًا محدّدًا من الصفوف التي تنتجها العقدة الفرعية.
• Offset
| offset: 10
| records returned: 1