查詢執行參考資料

本頁面說明使用 Query Explain 執行查詢的輸出結果。如要瞭解如何使用查詢說明功能執行查詢,請參閱「使用查詢說明功能分析查詢執行作業」。

常見概念

執行樹狀結構中會使用下列常見概念和術語。

資料列和記錄

「列」和「記錄」這兩個詞彙通常是指文件或索引項目。

變數

$ 表示在執行樹狀結構中建立或參照的變數。例如:$foo_1。這些變數通常用於參照文件內容,或查詢執行期間評估的運算式值。

執行節點中可能出現下列內部變數:

  • $__key__:鍵是文件的內部 ID。這是絕對的專屬 ID,包含專案、資料庫和文件的完整路徑。
  • $__id__:ID 是集合中文件的專屬 ID。 在單一集合中不得重複。
  • $rid:資料列 ID 是儲存空間中文件的內部 ID。在單一集合中不得重複。

假設 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 等於 1,並在 ["a" ASC, "b" ASC] 的索引上運作,則需要掃描並傳回 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 等於 $user_id,且 date_placed 等於 "2025-08-10",並在 ["user" ASC, "date_placed" ASC] 的索引上執行,則會使用執行階段的 $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: equal($user_1, $user_id) AND equal($date_placed_1, "2025-08-10")
| records returned: 1
| records scanned: 1

擷取

將提供的資料列 ID 重新加入主要儲存空間中的實際資料列內容。如果父項節點 (或最終查詢結果) 需要文件中的部分欄位,則必須提供 Fetch。

• Fetch
|  order: PRESERVE_INPUT_ORDER
|  peak memory usage: 4.00 KiB (4,096 B)
|  properties: *
|  records returned: 1

LookupById

依 ID 查詢外部集合中的文件,藉此執行彙整作業。要查詢的 ID 來自輸入文件中的欄位。查詢結果會以新欄位的形式新增至輸入文件。

• 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
|  expression: foo AS unnested_foo

限制

限制傳回至父項節點的資料列數量。

• Limit
|  limit: 10
|  records returned: 1

偏移

略過子節點產生的指定資料列數。

• Offset
|  offset: 10
|  records returned: 1