クエリ実行のリファレンス
このページでは、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