クエリ実行のリファレンス

このページでは、Query Explain で実行されたクエリの出力について説明します。 Query Explain を使用してクエリを実行する方法については、Query Explain でクエリの実行を分析するをご覧ください。

共通のコンセプト

実行ツリー全体で、次の一般的なコンセプトと用語が使用されています。

行とレコード

レコードという用語は、ドキュメントまたはインデックス エントリを一般的に指すために使用されます。

変数

$ は、実行ツリーで作成または参照される変数を示します。例: $foo_1。これらの変数は通常、ドキュメントの内容や、クエリの実行中に評価された式の値を参照するために使用されます。

実行ノードには、次の内部変数を使用できます。

  • $__key__ - キーはドキュメントの内部識別子です。これは、プロジェクト、データベース、ドキュメントの完全なパスを含む絶対一意識別子です。
  • $__id__ - ID は、コレクション内のドキュメントの一意の識別子です。これは、単一のコレクション内で一意です。
  • $rid - 行 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

1 回の読み取りオペレーションで実行できる、ストレージ内の静的な連続した行範囲のスキャンを表します。

key ordering length は、元のキーの順序を維持して返す必要があるキーの数を指します。[k1, k2, k3] のスキーマでは、key ordering length が 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: $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

外部コレクションのドキュメントを 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 に基づいて右入力で一致する行をスキャンすることで、2 つのデータセット(左と右)間の結合を実行します。

join_type は結合のタイプを示します。たとえば、LEFT_OUTER は、左側の入力のすべての行が出力に少なくとも 1 回含まれることを意味します。左側の行が join_condition に基づいて右側の入力のどの行とも一致しない場合でも、その行は右側の入力の列の null 値とともに含まれます。

• NestedLoopJoin
|  join_type: LEFT_OUTER
|  join_condition: $eq($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

一度に 1 つのグループの状態のみを維持する特殊な集計ノード。ピーク時のメモリ使用量を削減します。基盤となる子ノードがグループを順番に返す場合に使用されます。たとえば、フィールドのインデックスを使用しながら、そのフィールドの個別の値でグループ化する場合などです。

• 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
├── • 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

(レコード数 1,655)。

子ノードによって生成された行数をカウントし、現在のカウントを 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