文档

分析查询计划

学习如何阅读和分析查询计划,以了解查询执行步骤和数据组织,并找到性能瓶颈。

当您查询 InfluxDB v3 时,查询器为执行查询制定一个查询计划。该引擎试图确定查询结构和数据的最佳计划。通过学习如何生成和解释查询计划的报告,您可以更好地了解查询是如何执行的,并识别影响查询性能的瓶颈。

例如,如果查询计划显示您的查询读取了大量的 Parquet 文件,您可以采取以下措施来优化查询,例如添加过滤器以读取较少的数据或配置您的集群存储更少和更大的文件。

使用 EXPLAIN 关键字查看查询计划

使用 EXPLAIN 关键字(以及可选的 ANALYZEVERBOSE 关键字)来查看查询的查询计划。

使用 Python 和 pandas 查看 EXPLAIN 报告

阅读 EXPLAIN 报告

当您使用 EXPLAIN 关键字来查看查询计划 时,报告包含以下内容

阅读查询计划

计划以 树形格式 表示 - 每个计划都是一个倒置的树,执行和数据流从 叶节点(计划中最内层的步骤)流向外部的 分支节点。无论是阅读逻辑计划还是物理计划,请记住以下内容

  • 叶节点 开始,向上阅读。
  • 在计划的顶部,根节点 代表最终的综合步骤。

物理计划 中,每个步骤都是一个 ExecutionPlan 节点,它接收输入数据表达式和输出需求,并计算数据分区。

使用以下步骤分析查询计划并估计完成查询所需的工作量。无论计划看起来多么大或复杂,这些步骤都适用。

  1. 从最缩进的步骤(叶节点)开始,向上阅读。
  2. 了解每个 ExecutionPlan 节点 的任务 - 例如,一个包含叶节点的 UnionExec 节点意味着 UnionExec 连接所有叶节点的输出。
  3. 对于每个表达式,回答以下问题
    • 计划输入数据的数据形状和大小是什么?
    • 计划输出的数据形状和大小是什么?

本指南的其余部分将指导您分析物理计划。了解查询计划中节点序列、角色、输入和输出的顺序可以帮助您估计总体工作量并找到查询中的潜在瓶颈。

SELECT - ORDER BY 查询的示例物理计划

以下示例显示了如何阅读 EXPLAIN 报告和物理查询计划。

给定 h20 测量数据以及以下查询

EXPLAIN SELECT city, min_temp, time FROM h2o ORDER BY city ASC, time DESC;

输出类似于以下内容

EXPLAIN 报告

| plan_type     | plan                                                                     |
+---------------+--------------------------------------------------------------------------+
| logical_plan  | Sort: h2o.city ASC NULLS LAST, h2o.time DESC NULLS FIRST                 |
|               |   TableScan: h2o projection=[city, min_temp, time]                       |
| physical_plan | SortPreservingMergeExec: [city@0 ASC NULLS LAST,time@2 DESC]             |
|               |   UnionExec                                                              |
|               |     SortExec: expr=[city@0 ASC NULLS LAST,time@2 DESC]                   |
|               |       ParquetExec: file_groups={...}, projection=[city, min_temp, time]  |
|               |     SortExec: expr=[city@0 ASC NULLS LAST,time@2 DESC]                   |
|               |       ParquetExec: file_groups={...}, projection=[city, min_temp, time]  |
|               |                                                                          |

EXPLAIN SELECT city, min_temp, time FROM h2o ORDER BY city ASC, time DESC; 的输出

物理计划中的每个步骤或 节点 都是一个 ExecutionPlan 名称和包含相关查询部分的关键值 表达式 - 例如,EXPLAIN 报告物理计划中的第一个节点是一个 ParquetExec 执行计划

ParquetExec: file_groups={...}, projection=[city, min_temp, time]

因为 ParquetExecRecordBatchesExec 节点检索和扫描 InfluxDB 查询中的数据,所以每个查询计划都以一个或多个这些节点开始。

物理计划数据流

数据在查询计划中向上流动。

以下图表显示了 EXPLAIN 报告物理计划中的数据流和节点顺序

SortPreservingMergeExec
UnionExec
SortExec
ParquetExec
SortExec
ParquetExec

EXPLAIN 报告物理计划中的执行和数据流。 ParquetExec 节点并行执行,UnionExec 组合它们的输出。

以下步骤总结了 物理计划执行和数据流

  1. 两个 ParquetExec 计划并行,从 Parquet 文件中读取数据
    • 每个 ParquetExec 节点处理一个或多个 文件组
    • 每个文件组包含一个或多个 Parquet 文件路径。
    • ParquetExec 节点并行处理其组,依次读取每个组的文件。
    • 输出是一系列数据流到相应的 SortExec 节点。
  2. 并行排序的 SortExec 节点按 city(升序)和 time(降序)对数据进行排序。SortPreservingMergeExec 计划需要排序。
  3. UnionExec 节点将流连接起来,以合并并行 SortExec 节点的输出。
  4. SortPreservingMergeExec 节点将来自 UnionExec 的先前排序和合并的数据合并。

空结果集的示例 EXPLAIN 报告

如果您的表中不包含查询中的时间范围数据,物理计划从 EmptyExec 叶子节点开始 - 例如

ProjectionExec: expr=[temp@0 as temp]
    SortExec: expr=[time@1 ASC NULLS LAST]
        EmptyExec: produce_one_row=false

分析领先数据的查询计划

以下部分指导您分析典型的时间序列用例的物理查询计划 - 聚合最近写入(前沿)数据。尽管查询和计划比前面的示例更复杂,但您将遵循相同的 步骤读取查询计划。在学习如何读取查询计划后,您将了解 ExecutionPlans、数据流和潜在查询瓶颈。

示例数据

考虑以下以“行协议的块”表示的 h20 数据,写入 InfluxDB

// h20 data
// The following data represents 5 batches, or "chunks", of line protocol
// written to InfluxDB.
// - Chunks 1-4 are ingested and each is persisted to a separate partition file in storage.
// - Chunk 5 is ingested and not yet persisted to storage.
// - Chunks 1 and 2 cover short windows of time that don't overlap times in other chunks.
// - Chunks 3 and 4 cover larger windows of time and the time ranges overlap each other.
// - Chunk 5 contains the largest time range and overlaps with chunk 4, the Parquet file with the largest time-range.
// - In InfluxDB, a chunk never duplicates its own data.
//
// Chunk 1: stored Parquet file
// - time range: 50-249
// - no duplicates in its own chunk
// - no overlap with any other chunks
[
"h2o,state=MA,city=Bedford min_temp=71.59 150",
"h2o,state=MA,city=Boston min_temp=70.4, 50",
"h2o,state=MA,city=Andover max_temp=69.2, 249",
],

// Chunk 2: stored Parquet file
// - time range: 250-349
// - no duplicates in its own chunk
// - no overlap with any other chunks
// - adds a new field (area)
[
"h2o,state=CA,city=SF min_temp=79.0,max_temp=87.2,area=500u 300",
"h2o,state=CA,city=SJ min_temp=75.5,max_temp=84.08 349",
"h2o,state=MA,city=Bedford max_temp=78.75,area=742u 300",
"h2o,state=MA,city=Boston min_temp=65.4 250",
],

// Chunk 3: stored Parquet file
// - time range: 350-500
// - no duplicates in its own chunk
// - overlaps chunk 4
[
"h2o,state=CA,city=SJ min_temp=77.0,max_temp=90.7 450",
"h2o,state=CA,city=SJ min_temp=69.5,max_temp=88.2 500",
"h2o,state=MA,city=Boston min_temp=68.4 350",
],

// Chunk 4: stored Parquet file
// - time range: 400-600
// - no duplicates in its own chunk
// - overlaps chunk 3
[
 "h2o,state=CA,city=SF min_temp=68.4,max_temp=85.7,area=500u 600",
 "h2o,state=CA,city=SJ min_temp=69.5,max_temp=89.2 600",  // duplicates row 3 in chunk 5
 "h2o,state=MA,city=Bedford max_temp=80.75,area=742u 400", // overlaps chunk 3
 "h2o,state=MA,city=Boston min_temp=65.40,max_temp=82.67 400", // overlaps chunk 3
],

// Chunk 5: Ingester data
// - time range: 550-700
// - overlaps and duplicates data in chunk 4
[
"h2o,state=MA,city=Bedford max_temp=88.75,area=742u 600", // overlaps chunk 4
"h2o,state=CA,city=SF min_temp=68.4,max_temp=85.7,area=500u 650",
"h2o,state=CA,city=SJ min_temp=68.5,max_temp=90.0 600", // duplicates row 2 in chunk 4
"h2o,state=CA,city=SJ min_temp=75.5,max_temp=84.08 700",
"h2o,state=MA,city=Boston min_temp=67.4 550", // overlaps chunk 4
]

以下查询选择所有数据

SELECT state, city, min_temp, max_temp, area, time
FROM h2o
ORDER BY state asc, city asc, time desc;

输出如下

+-------+---------+----------+----------+------+--------------------------------+
| state | city    | min_temp | max_temp | area | time                           |
+-------+---------+----------+----------+------+--------------------------------+
| CA    | SF      | 68.4     | 85.7     | 500  | 1970-01-01T00:00:00.000000650Z |
| CA    | SF      | 68.4     | 85.7     | 500  | 1970-01-01T00:00:00.000000600Z |
| CA    | SF      | 79.0     | 87.2     | 500  | 1970-01-01T00:00:00.000000300Z |
| CA    | SJ      | 75.5     | 84.08    |      | 1970-01-01T00:00:00.000000700Z |
| CA    | SJ      | 68.5     | 90.0     |      | 1970-01-01T00:00:00.000000600Z |
| CA    | SJ      | 69.5     | 88.2     |      | 1970-01-01T00:00:00.000000500Z |
| CA    | SJ      | 77.0     | 90.7     |      | 1970-01-01T00:00:00.000000450Z |
| CA    | SJ      | 75.5     | 84.08    |      | 1970-01-01T00:00:00.000000349Z |
| MA    | Andover |          | 69.2     |      | 1970-01-01T00:00:00.000000249Z |
| MA    | Bedford |          | 88.75    | 742  | 1970-01-01T00:00:00.000000600Z |
| MA    | Bedford |          | 80.75    | 742  | 1970-01-01T00:00:00.000000400Z |
| MA    | Bedford |          | 78.75    | 742  | 1970-01-01T00:00:00.000000300Z |
| MA    | Bedford | 71.59    |          |      | 1970-01-01T00:00:00.000000150Z |
| MA    | Boston  | 67.4     |          |      | 1970-01-01T00:00:00.000000550Z |
| MA    | Boston  | 65.4     | 82.67    |      | 1970-01-01T00:00:00.000000400Z |
| MA    | Boston  | 68.4     |          |      | 1970-01-01T00:00:00.000000350Z |
| MA    | Boston  | 65.4     |          |      | 1970-01-01T00:00:00.000000250Z |
| MA    | Boston  | 70.4     |          |      | 1970-01-01T00:00:00.000000050Z |
+-------+---------+----------+----------+------+--------------------------------+

示例查询

以下查询从 样本数据 中选择前沿数据

SELECT city, count(1)
FROM h2o
WHERE time >= to_timestamp(200) AND time < to_timestamp(700)
  AND state = 'MA'
GROUP BY city
ORDER BY city ASC;

输出如下

+---------+-----------------+
| city    | COUNT(Int64(1)) |
+---------+-----------------+
| Andover | 1               |
| Bedford | 3               |
| Boston  | 4               |
+---------+-----------------+

领先数据查询的 EXPLAIN 报告

以下查询生成前面的 样本查询EXPLAIN 报告

EXPLAIN SELECT city, count(1)
FROM h2o
WHERE time >= to_timestamp(200) AND time < to_timestamp(700)
  AND state = 'MA'
GROUP BY city
ORDER BY city ASC;

前沿数据查询的 EXPLAIN 报告

样本数据 中的注释告诉您哪些数据块 重叠 或在其他块中重复数据。如果两个数据块在某个时间段内都存在数据,则这两个数据块重叠。您将在本指南的后面部分学习如何在查询计划中识别重叠和重复数据

与样本数据不同,您可能不知道重叠或重复的位置。物理计划可以揭示您的数据中的重叠和重复,以及它们对查询的影响 - 例如,在学习如何读取物理计划后,您可能将数据扫描步骤总结如下

  • 查询执行从两个并行运行的 ParquetExec 和一个 RecordBatchesExec 执行计划开始。
  • 第一个 ParquetExec 节点读取两个不与其他文件重叠且不重复数据的文件;这些文件不需要去重。
  • 第二个 ParquetExec 节点读取两个重叠的文件,这些文件还重叠了在 RecordBatchesExec 节点中扫描的导入数据;查询计划必须在完成查询之前包括这些节点的前置去重过程。

以下部分分析示例物理计划中 ExecutionPlan 节点的结构和参数。示例包括 DataFusion 和 InfluxDB 特定的 ExecutionPlan 节点

定位物理计划

要开始分析查询的物理计划,请在 EXPLAIN 报告 中找到 plan_type 列值为 physical_plan 的行。该行的 plan 列包含物理计划。

阅读物理计划

以下部分遵循以下步骤:阅读查询计划并检查物理计划节点及其输入和输出。

阅读查询计划的执行流程,始终从最内层(叶)节点开始,向上读取到最外层的根节点。

物理计划叶节点

Query physical plan leaf node structures

物理计划中的叶节点结构

数据扫描节点(ParquetExec 和 RecordBatchesExec)

示例物理计划包含三个叶节点——执行流程开始的内部节点

由于ParquetExecRecordBatchesExec检索和扫描查询数据,因此每个查询计划都以一个或多个这些节点开始。

ParquetExecRecordBatchesExec节点数量及其参数值可以告诉您查询检索了哪些数据(以及多少数据),以及计划如何有效地处理数据的组织(例如分区和去重)。

为了方便,本指南使用ParquetExec_AParquetExec_B来命名示例物理计划中的ParquetExec节点。从物理计划的顶部开始阅读,ParquetExec_A是物理计划中的第一个叶节点,而ParquetExec_B是最后一个(底部)叶节点。

这些名称表示节点在报告中的位置,而不是它们的执行顺序。

ParquetExec_A

ParquetExec: file_groups={2 groups: [[1/1/b862a7e9b329ee6a418cde191198eaeb1512753f19b87a81def2ae6c3d0ed237/243db601-f3f1-401b-afda-82160d8cc1a8.Parquet], [1/1/b862a7e9b329ee6a418cde191198eaeb1512753f19b87a81def2ae6c3d0ed237/f5fb7c7d-16ac-49ba-a811-69578d05843f.Parquet]]}, projection=[city, state, time], output_ordering=[state@1 ASC, city@0 ASC, time@2 ASC], predicate=time@5 >= 200 AND time@5 < 700 AND state@4 = MA, pruning_predicate=time_max@0 >= 200 AND time_min@1 < 700 AND state_min@2 <= MA AND MA <= state_max@3                                           |

ParquetExec_A,第一个ParquetExec节点

ParquetExec_A具有以下特性

file_groups

file group是一系列文件,供操作员读取。文件通过路径引用

  • 1/1/b862a7e9b.../243db601-....parquet
  • 1/1/b862a7e9b.../f5fb7c7d-....parquet

路径结构表示您的数据是如何组织的。您可以使用文件路径收集有关查询的更多信息——例如

  • 在目录中查找文件信息(例如:大小和行数)
  • 从对象存储中下载Parquet文件以进行调试
  • 找到查询读取了多少个分区

路径具有以下结构

<namespace_id>/<table_id>/<partition_hash_id>/<uuid_of_the_file>.Parquet
    1         /    1    /b862a7e9b329ee6a4.../243db601-f3f1-4....Parquet
  • namespace_id:正在查询的命名空间(数据库)
  • table_id:正在查询的表(测量)
  • partition_hash_id:此文件所属的分区。您可以计算分区ID以找到查询读取了多少个分区。
  • uuid_of_the_file:文件标识符。

ParquetExec并行处理组,并按顺序读取每个组中的文件。

file_groups={2 groups: [[1/1/b862a7e9b329ee6a4/243db601....parquet], [1/1/b862a7e9b329ee6a4/f5fb7c7d....parquet]]}
  • {2 groups: [[file], [file]}:ParquetExec_A接收两个组,每个组有一个文件。因此,ParquetExec_A并行读取两个文件。
projection

projection列出了ExecutionPlan要读取和输出的表列。

projection=[city, state, time]
  • [city, state, time]:样本数据包含许多列,但样本查询要求查询器只读取三个
output_ordering

output_ordering指定了ExecutionPlan输出的排序顺序。如果输出应该排序,并且规划者知道顺序,则查询规划器传递此参数。

output_ordering=[state@2 ASC, city@1 ASC, time@3 ASC, __chunk_order@0 ASC]

在存储数据到Parquet文件时,InfluxDB会对数据进行排序以提高存储压缩和查询效率,规划器会尝试尽可能长时间地保留该顺序。通常,ParquetExec接收到的output_ordering值是存储数据的排序(或排序的子集)。

根据设计,RecordBatchesExec数据是不排序的。

在示例中,规划器指定ParquetExec_A使用现有的排序顺序state ASC, city ASC, time ASC,进行输出。

要查看存储数据的排序顺序,为SELECT ALL查询生成一个EXPLAIN报告,例如

EXPLAIN SELECT * FROM TABLE_NAME WHERE time > now() - interval '1 hour'

如果查询返回太多数据,请减少时间范围。

谓词

谓词是查询中指定的数据过滤器。

predicate=time@5 >= 200 AND time@5 < 700 AND state@4 = MA
剪枝谓词

剪枝谓词是从谓词值创建的,并且是用于从所选分区中剪枝数据和文件的实际谓词。默认过滤器按time过滤文件。

pruning_predicate=time_max@0 >= 200 AND time_min@1 < 700 AND state_min@2 <= MA AND MA <= state_max@3

在生成物理计划之前,一个额外的分区剪枝步骤使用分区列上的谓词来剪枝分区。

RecordBatchesExec

RecordBatchesExec: chunks=1, projection=[__chunk_order, city, state, time]
RecordBatchesExec

RecordBatchesExec是InfluxDB特定的ExecutionPlan实现,用于从Ingester检索最近写入的、尚未持久化的数据。

在示例中,RecordBatchesExec包含以下表达式

是从Ingester接收到的数据块数量。

chunks=1
  • chunks=1RecordBatchesExec接收一个数据块。
projection

projection列表指定节点要读取和输出的列或表达式。

[__chunk_order, city, state, time]
  • __chunk_order:对块和文件进行排序以进行去重
  • city, state, time:与ParquetExec_A投影中指定的相同列

在数据扫描节点中存在__chunk_order表示节点之间可能存在数据重叠,可能存在重复。

ParquetExec_B

示例物理计划的底部叶节点是另一个ParquetExec操作符,ParquetExec_B

ParquetExec_B表达式
ParquetExec:
  file_groups={2 groups: [[1/1/b862a7e9b.../2cbb3992-....Parquet],
   [1/1/b862a7e9b.../9255eb7f-....Parquet]]},
  projection=[__chunk_order, city, state, time],
  output_ordering=[state@2 ASC, city@1 ASC, time@3 ASC, __chunk_order@0 ASC],
  predicate=time@5 >= 200 AND time@5 < 700 AND state@4 = MA,
  pruning_predicate=time_max@0 >= 200 AND time_min@1 < 700 AND state_min@2 <= MA AND MA <= state_max@3
ParquetExec_B,第二个ParquetExec

由于ParquetExec_B存在重叠,因此projectionoutput_ordering表达式使用RecordBatchesExec projection中使用的__chunk_order列。

在数据扫描节点中存在__chunk_order表示节点之间可能存在数据重叠,可能存在重复。

ParquetExec_B的其余表达式与ParquetExec_A中的表达式类似。

查询计划如何分配扫描数据

如果您比较file_group路径在ParquetExec_A中的路径与ParquetExec_B中的路径,您会发现两者都包含来自同一分区的文件

1/1/b862a7e9b329ee6a4.../...

规划器可能出于几个原因将来自同一分区的文件分配到不同的扫描节点,包括处理重叠的优化——例如

  • 将非重叠文件与非重叠文件分开以最小化去重所需的工作(如本例所示)
  • 将非重叠文件分配以增加并行执行

分析分支结构

从数据扫描节点输出数据后,它流向上一个父(外部)节点。

在示例计划中

  • 每个叶节点是处理扫描数据的节点分支的第一个步骤。
  • 三个分支并行执行。
  • 在叶节点之后,每个分支包含以下类似的节点结构
...
CoalesceBatchesExec: target_batch_size=8192
    FilterExec: time@3 >= 200 AND time@3 < 700 AND state@2 = MA
    ...
  • FilterExec: time@3 >= 200 AND time@3 < 700 AND state@2 = MA:对time@3 >= 200 AND time@3 < 700 AND state@2 = MA条件的数据进行筛选,并保证所有数据都被剪枝。
  • CoalesceBatchesExec: target_batch_size=8192:将小批次合并成更大的批次。请参阅DataFusion [CoalesceBatchesExec]文档。

排序尚未持久化的数据

RecordBatchesExec分支中,紧跟在CoalesceBatchesExec之后的节点是SortExec节点

SortExec: expr=[state@2 ASC,city@1 ASC,time@3 ASC,__chunk_order@0 ASC]

该节点使用指定的表达式 state ASC, city ASC, time ASC, __chunk_order ASC 对尚未持久化的数据进行排序。ParquetExec_A 和 ParquetExec_B 都没有类似的节点,因为对象存储中的数据已经按照给定的顺序(由 IngesterCompactor)排序;查询计划只需对来自 Ingester 的数据进行排序。

识别重叠和重复数据

在示例物理计划中,ParquetExec_B 和 RecordBatchesExec 节点共享以下父节点

...
DeduplicateExec: [state@2 ASC,city@1 ASC,time@3 ASC]
    SortPreservingMergeExec: [state@2 ASC,city@1 ASC,time@3 ASC,__chunk_order@0 ASC]
        UnionExec
            ...
重叠数据节点结构
  1. UnionExec:通过连接分区将多个输入数据流合并。 UnionExec 不执行任何合并,执行速度快。
  2. SortPreservingMergeExec: [state@2 ASC,city@1 ASC,time@3 ASC,__chunk_order@0 ASC]:合并已排序的数据;表示其下方节点中的数据已排序。输出数据是单个排序流。
  3. DeduplicateExec: [state@2 ASC,city@1 ASC,time@3 ASC]:对排序数据流进行去重。由于 SortPreservingMergeExec 确保单个排序流,它通常(但不总是)位于 DeduplicateExec 之前。

DeduplicateExec 节点表示包含的节点有 重叠数据–文件或批次中的数据时间戳与另一个文件或批次中的数据时间戳相同。由于 InfluxDB 组织数据的方式,数据永远不会在文件内部重复。

在示例中,DeduplicateExec 节点包含 ParquetExec_B 和 RecordBatchesExec 节点,这表明 ParquetExec_B 文件组 文件与尚未持久化的数据重叠。

以下 示例数据 摘录显示了文件和 Ingester 数据之间的重叠数据

// Chunk 4: stored Parquet file
//   - time range: 400-600
[
 "h2o,state=CA,city=SF min_temp=68.4,max_temp=85.7,area=500u 600",
],

// Chunk 5: Ingester data
//   - time range: 550-700
//   - overlaps and duplicates data in chunk 4
[
"h2o,state=MA,city=Bedford max_temp=88.75,area=742u 600", // overlaps chunk 4
...
"h2o,state=MA,city=Boston min_temp=67.4 550", // overlaps chunk 4
]

如果文件或摄取的数据重叠,查询器必须在查询计划中包含 DeduplicateExec 以删除任何重复项。DeduplicateExec 并不一定表示数据重复。如果计划读取许多文件并对所有文件进行去重,这可能是因为以下原因

  • 文件包含重复数据
  • 对象存储有许多尚未由 Compactor 压缩的小重叠文件。压缩后,您的查询可能会表现得更好,因为它需要读取的文件更少
  • Compactor 追不上。如果数据没有重复,并且在压缩后您仍然有许多小重叠文件,那么您可能需要审查 Compactor 的工作负载并根据需要添加更多资源

没有 DeduplicateExec 节点的叶子节点不需要去重,且不与其他文件或 Ingester 数据重叠——例如,ParquetExec_A 没有重叠

ProjectionExec:...
    CoalesceBatchesExec:...
        FilterExec:...
            ParquetExec:...

DeduplicateExec 节点的缺失意味着文件没有重叠。

数据扫描输出

ProjectionExec 节点过滤列,以便仅保留 city 列在输出中

`ProjectionExec: expr=[city@0 as city]`
最终处理

在每个叶子节点中去重和过滤数据后,计划将输出合并,然后对最终结果应用聚合和排序运算符

| physical_plan | SortPreservingMergeExec: [city@0 ASC NULLS LAST]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
|               |   SortExec: expr=[city@0 ASC NULLS LAST]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
|               |     AggregateExec: mode=FinalPartitioned, gby=[city@0 as city], aggr=[COUNT(Int64(1))]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
|               |       CoalesceBatchesExec: target_batch_size=8192                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
|               |         RepartitionExec: partitioning=Hash([city@0], 4), input_partitions=4                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|               |           AggregateExec: mode=Partial, gby=[city@0 as city], aggr=[COUNT(Int64(1))]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
|               |             RepartitionExec: partitioning=RoundRobinBatch(4), input_partitions=3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
|               |               UnionExec

聚合、排序和最终输出的运算符结构。

  • UnionExec:合并数据流。请注意,输出流的数量与输入流的数量相同——UnionExec 节点是一个中间步骤,用于实际合并或拆分数据流的下游运算符。
  • RepartitionExec: partitioning=RoundRobinBatch(4), input_partitions=3:将三个输入流以轮询方式分成四个输出流。此计划将流拆分以增加并行执行。
  • AggregateExec: mode=Partial, gby=[city@0 as city], aggr=[COUNT(Int64(1))]:按查询中指定的方式分组数据:city, count(1)。此节点分别对四个流进行聚合,并输出四个流,由mode=Partial表示——数据未完全聚合。
  • RepartitionExec: partitioning=Hash([city@0], 4), input_partitions=4:在Hash([city])上重新分配数据,并分为四个流——每个流包含一个城市的所有数据。
  • AggregateExec: mode=FinalPartitioned, gby=[city@0 as city], aggr=[COUNT(Int64(1))]:对数据进行最终聚合(aggr=[COUNT(Int64(1))])。mode=FinalPartitioned表示数据已经按城市分区,不需要通过AggregateExec进一步分组。
  • SortExec: expr=[city@0 ASC NULLS LAST]:根据查询指定的条件对四个数据流按city排序。
  • SortPreservingMergeExec: [city@0 ASC NULLS LAST]:合并并排序四个排序后的流以生成最终输出。

在上面的示例中,EXPLAIN报告显示了查询计划而不执行查询。要查看运行时指标,例如计划及其操作符的执行时间,请使用EXPLAIN ANALYZE生成报告,并在必要时使用跟踪进行进一步调试。


这个页面有帮助吗?

感谢您的反馈!


Flux的未来

Flux将进入维护模式。您将继续按照当前的方式使用它,而无需对代码进行任何更改。

阅读更多

InfluxDB v3增强功能和InfluxDB Clustered现已全面上市

包括更快的查询性能和管理工具在内的新功能推动了InfluxDB v3产品线的发展。InfluxDB Clustered现已全面上市。

InfluxDB v3性能和功能

InfluxDB v3产品线在查询性能方面取得了显著提升,并提供了新的管理工具。这些增强功能包括用于监控InfluxDB集群健康的操作仪表板,InfluxDB Cloud Dedicated中的单点登录(SSO)支持,以及用于令牌和数据库的新管理API。

了解新的v3增强功能


InfluxDB Clustered全面上市

现在InfluxDB集群版已全面上市,为您在自管理堆栈中带来InfluxDB v3的强大功能。

与我们讨论InfluxDB集群版