查询执行参考

本页介绍了使用“查询说明”执行的查询的输出。 如需了解如何使用查询解释执行查询,请参阅使用查询解释分析查询执行情况

常见概念

整个执行树中使用了以下常见概念和术语。

行和记录

术语“行”和“记录”用于泛指文档或索引条目。

变量

以下内部变量可以出现在执行节点中:

  • __key__- 键是文档的内部标识符。这是一个绝对唯一标识符,包含项目、数据库和文档的完整路径。
  • __id__-该 ID 是相应集合中某个文档的唯一标识符。 此 ID 在单个集合中是唯一的。
  • __$0__…__$N__- 这些是执行树中创建或引用的特定于上下文的变量。这些变量通常用于引用文档的内容或在执行查询期间评估的表达式的值。

以一个使用 extend 节点从文档 __key__ 中提取 __id__ 的示例为例:

Extend
    |  expressions: [_id(__key__) AS __id__]
    |  records returned: 1

约束和范围

某些扫描节点使用 constraintsranges 属性来描述扫描的值范围。这些属性使用包含值列表的范围树格式。这些值与索引定义中显示的键的有序列表相对应。例如,树中显示的第一个范围(此处为 (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 字段的值会映射到变量 __$6__,而 date_placed 的值会映射到 __$7__

index: type=CollectionGroupIndex, id=CICAgOjXh4EK, keys=[user ASC, date_placed ASC, __path__ ASC]
keys: [__$6__ ASC, __$7__ ASC, __path__ ASC]

执行节点

查询执行树可以包含以下节点。

SeekingScan

表示一种动态扫描,其中返回的行可能不在索引的单个连续范围内,并且必须执行多次不同的扫描才能满足查询。

例如,如果查询中存在 ab 等于 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: [__$1__ ASC, __$2__ 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: [__$1__ ASC, __$2__ 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: [__$1__ ASC, __$2__ ASC, __key__ ASC]
| properties: Selection { a }
| ranges: /
          |----(-∞..+∞)
| 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

TableScan

对集合进行无序的完整扫描。在运行没有关联索引的查询时使用。

顺序可以是 STABLEUNDEFINED,其中 STABLE 表示确定性排序。

• TableScan
|  order: STABLE
|  properties: *
|  records returned: 1
|  records scanned: 1
|  source: (default)#/**/collection

HashAggregate

基于哈希的聚合操作实现。需要在内存中具体化整个组,然后才能返回结果,并且不得超过查询内存限制

• HashAggregate
|  aggregations: [sum(__$0__) AS total]
|  groups: [a]
|  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) 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

限制

投影一组要传递给父节点的属性。通过在不相关字段对查询的其余部分不再有意义时立即阻止其传播,来减少内存用量。

• Restrict
|  expressions: [foo AS foo, bar AS bar]
|  records returned: 0

延期

向结果集中的每一行添加一组字段。在向文档添加字段时使用,并用作支持更复杂操作的中间节点。

• Extend
|  expressions: ["bar" AS foo]
|  records returned: 1

过滤

仅当行与提供的表达式匹配时,才选择性地返回这些行。

• Filter
|  expression: $eq(foo, "bar")
|  records returned: 1

生成要处理的一系列字面值。主要在将一组文档作为查询的输入时使用。

• Values
| expression: [{__key__=/col/1}, {__key__=/col/2}]

ReplaceWith

将子节点生成的行的字段替换为所提供的 map 表达式中的字段。

• ReplaceWith
|  map: map("full_name", str_concat(first_name, " ", last_name)), current_context())
|  records returned: 1

Unnest

取消嵌套子节点生成的值。

• Unnest
|  expression: foo AS unnested_foo

限制

限制返回到父节点的行数。

• Limit
|  limit: 10
|  records returned: 1

偏移值

跳过子节点生成的一组指定数量的行。

• Offset
|  offset: 10
|  records returned: 1

删除

从子节点生成的结果中舍弃指定的一组字段。

• Drop
|  fields to drop: [__key__]
|  records returned: 1