หน้านี้อธิบายเอาต์พุตของการค้นหาที่ดำเนินการด้วย Query Explain ดูวิธีเรียกใช้การค้นหาด้วย Query Explain ได้ที่วิเคราะห์การเรียกใช้การค้นหาด้วย Query Explain
แนวคิดทั่วไป
แนวคิดและคำศัพท์ที่พบบ่อยต่อไปนี้ใช้ตลอดทั้งแผนผังการดำเนินการ
แถวและระเบียน
คำว่าแถวและระเบียนใช้เพื่ออ้างอิงถึงเอกสารหรือรายการดัชนีโดยทั่วไป
ตัวแปร
$ หมายถึงตัวแปรที่สร้างขึ้นหรืออ้างอิงในแผนผังการดำเนินการ ตัวอย่างเช่น $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 หากโหนดหลัก (หรือผลการค้นหาสุดท้าย) ต้องใช้ชุดย่อยของช่องจากเอกสาร
• 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
ดำเนินการรวมระหว่างข้อมูล 2 ชุด (ซ้ายและขวา) โดยทำซ้ำในแต่ละแถวของอินพุตด้านซ้าย และสแกนอินพุตด้านขวาเพื่อหาแถวที่ตรงกันตาม join_condition สำหรับแถวด้านซ้ายแต่ละแถว
join_type ระบุประเภทของการรวม เช่น LEFT_OUTER หมายความว่าแถวทั้งหมดจากอินพุตด้านซ้ายจะรวมอยู่ในเอาต์พุตอย่างน้อย 1 ครั้ง
หากแถวด้านซ้ายไม่ตรงกับแถวใดๆ ในอินพุตด้านขวาตาม join_condition ระบบจะยังคงรวมแถวดังกล่าวไว้ โดยมีค่า Null สำหรับคอลัมน์จากอินพุตด้านขวา
• 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
ประเมินชุดนิพจน์ โดยกำหนดผลลัพธ์ให้กับชุดตัวแปร
• 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