इस पेज पर, Query Explain की मदद से की गई क्वेरी का आउटपुट दिखाया गया है. क्वेरी की व्याख्या करने की सुविधा का इस्तेमाल करके क्वेरी को चलाने का तरीका जानने के लिए, क्वेरी की व्याख्या करने की सुविधा का इस्तेमाल करके क्वेरी के एक्ज़ीक्यूशन का विश्लेषण करना लेख पढ़ें.
सामान्य कॉन्सेप्ट
एक्ज़ीक्यूशन ट्री में, इन सामान्य शब्दों और सिद्धांतों का इस्तेमाल किया जाता है.
लाइनें और रिकॉर्ड
लाइन और रिकॉर्ड शब्दों का इस्तेमाल, किसी दस्तावेज़ या इंडेक्स एंट्री के लिए सामान्य तौर पर किया जाता है.
वैरिएबल
$ एक वैरिएबल को दिखाता है, जिसे एक्ज़ीक्यूशन ट्री में बनाया या रेफ़र किया जाता है. उदाहरण के लिए: $foo_1. इन वैरिएबल का इस्तेमाल आम तौर पर, किसी दस्तावेज़ के कॉन्टेंट या क्वेरी के एक्ज़ीक्यूशन के दौरान, आकलन किए गए एक्सप्रेशन की वैल्यू को रेफ़र करने के लिए किया जाता है.
ये इंटरनल वैरिएबल, एक्ज़ीक्यूशन नोड में दिख सकते हैं:
$__key__- यह कुंजी, किसी दस्तावेज़ के लिए इंटरनल आइडेंटिफ़ायर होती है. यह प्रोजेक्ट, डेटाबेस, और दस्तावेज़ के पूरे पाथ के साथ एक यूनीक आइडेंटिफ़ायर होता है.$__id__- आईडी, कलेक्शन में मौजूद किसी दस्तावेज़ के लिए यूनीक आइडेंटिफ़ायर होता है. यह एक कलेक्शन में यूनीक होता है.$rid- लाइन का आईडी, स्टोरेज में मौजूद किसी दस्तावेज़ के लिए इंटरनल आइडेंटिफ़ायर होता है. यह एक कलेक्शन में यूनीक होता है.
यहां एक उदाहरण दिया गया है, जिसमें Compute नोड का इस्तेमाल करके, दस्तावेज़ __key__ से __id__ का हिसाब लगाया गया है:
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 एट्रिब्यूट के हिस्से के तौर पर कुंजियों की सूची होती है. साथ ही, Scan नोड में एक अलग keys एट्रिब्यूट होता है. Scan नोड में मौजूद keys एट्रिब्यूट, इंडेक्स की परिभाषा में मौजूद हर कुंजी के वैरिएबल के नाम को क्रम से दिखाता है. इन वैरिएबल का इस्तेमाल, स्कैन किए गए फ़ील्ड की रनटाइम वैल्यू को एग्ज़ीक्यूशन ट्री में ऊपर की ओर ले जाने के लिए किया जा सकता है.
इस उदाहरण में, मौजूदा दस्तावेज़ के लिए 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, ["a" ASC, "b" ASC] के इंडेक्स पर काम करने वाले 1 के बराबर है, उसे a की हर अलग वैल्यू के लिए, स्कैन करके एक अलग रेंज दिखानी होगी. यह रेंज, क्रम से न भी हो सकती है.
यह पूरी TableScan से ज़्यादा बेहतर है. हालांकि, यह ["b" ASC, "a" ASC] के कंपोज़िट इंडेक्स पर मौजूद एक SequentialScan से कम बेहतर है.
• 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" ASC, "date_placed" ASC] के इंडेक्स पर चल रही ऐसी क्वेरी जहां user, $user_id के बराबर है और date_placed, "2025-08-10" के बराबर है, रनटाइम के दौरान $user_id वैरिएबल की वैल्यू का इस्तेमाल करेगी. साथ ही, स्कैन की जाने वाली रेंज को सीमित करने के लिए, date_placed पर "2025-08-10" की शर्त का इस्तेमाल करेगी.
• 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: $eq($user_1, $user_id) AND $eq($date_placed_1, "2025-08-10")
| records returned: 1
| records scanned: 1
TableAccess
यह फ़ंक्शन, दी गई लाइन के आइडेंटिफ़ायर को प्राइमरी स्टोरेज से मिली लाइन के कॉन्टेंट के साथ फिर से जोड़ता है. अगर पैरंट नोड (या क्वेरी के फ़ाइनल नतीजे) को दस्तावेज़ों के फ़ील्ड के सबसेट की ज़रूरत होती है, तो TableAccess ज़रूरी है.
• TableAccess
| 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
लागू करें
यह फ़ंक्शन, डेटा के दो सेट (input और map) को जोड़ता है. इसके लिए, यह input की हर लाइन को दोहराता है. साथ ही, हर लाइन के लिए, map से नतीजे स्कैन करके दिखाता है.
join_type से पता चलता है कि शामिल होने का टाइप क्या है. उदाहरण के लिए, LEFT_OUTER
का मतलब है कि input की सभी पंक्तियों को आउटपुट में कम से कम एक बार शामिल किया गया है.
अगर किसी input लाइन को map साइड से कोई नतीजा नहीं मिलता है, तो भी उसे शामिल किया जाएगा. साथ ही, map साइड के कॉलम के लिए null वैल्यू शामिल की जाएंगी.
• Apply
| join_type: LEFT_OUTER
|
└── • input tree
| ...
└── • map 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
यह फ़ंक्शन, प्रॉपर्टी के तय किए गए सेट पर क्रम से लगाने की कार्रवाई करता है. यह फ़ंक्शन, सभी रिकॉर्ड को एक साथ मेमोरी में सेव करता है. इसके बाद, क्रम से लगाई गई वैल्यू दिखाता है. क्रम से लगाए गए सेट का साइज़, क्वेरी की मेमोरी की सीमा से तय होता है.
इसके बाद की सीमाएं तय करते समय, मेमोरी के इस्तेमाल को कम करने के लिए, टॉप-k सॉर्टिंग एल्गोरिदम का इस्तेमाल किया जाता है. इसकी मदद से, रिकॉर्ड के किसी भी बड़े सेट को क्रम से लगाया जा सकता है. हालांकि, इसके लिए यह ज़रूरी है कि k एलिमेंट को सेव करने के लिए इस्तेमाल की गई मेमोरी, तय सीमा से ज़्यादा न हो.
• MajorSort
| fields: [a ASC, b DESC]
| limit: 10
| peak memory usage: 4.00 KiB (4,096 B)
| records returned: 1
Concat
यह कई चाइल्ड नोड के नतीजों को एक साथ जोड़ता है और पैरंट नोड को नतीजा दिखाता है. यह नोड, एक से ज़्यादा बच्चों के लिए दिखने वाले नतीजों को नहीं हटाता. साथ ही, दिखाए गए नतीजों का क्रम तय नहीं होता.
• Concat
├── • TableAccess
...
├── • TableAccess
कंप्यूट
यह फ़ंक्शन, एक्सप्रेशन के सेट का आकलन करता है और नतीजों को वैरिएबल के सेट में असाइन करता है.
• 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
| expression: foo AS unnested_foo
सीमा
इससे पैरंट नोड को दिखाई जाने वाली पंक्तियों की संख्या सीमित हो जाती है.
• Limit
| limit: 10
| records returned: 1
ऑफ़सेट
यह विकल्प, चाइल्ड नोड से जनरेट हुई पंक्तियों की तय संख्या को छोड़ देता है.
• Offset
| offset: 10
| records returned: 1