本篇接着来分析 profile 文件的 Plan 和 ExecSummary 部分。

# Plan

这个部分是执行计划,可以看到所有的查询片段和节点。
SELECT COUNT(*), ss_sold_date_sk FROM tpcds_parquet.store_sales GROUP BY ss_sold_date_sk 需要扫描整个表,然后进行聚合操作。在这个 profile 中,有 3 个执行片段,5 个执行节点。

# F00:PLAN FRAGMENT

数据分发方式是 RANDOM,在三台机器执行,12 个实例,这个是因为设置了 MT_DOP=4,每台机器上有 4 个并发。
每个实例预估消耗的内存 26.00MB,预留内存 2.12MB,预留线程 1 个。

F00:PLAN FRAGMENT [RANDOM] hosts=3 instances=12
Per-Instance Resources: mem-estimate=26.00MB mem-reservation=2.12MB thread-reservation=1

# 00:SCAN HDFS

先是随机扫描 HDFS:

  • 表的分区有 1824 个,全部需要扫描,文件有 1824 个,数据大小是 196.95MB
  • 存储统计信息
  • 推算行数未开启,最大的 scan range 行数为 130.09K
  • 预估内存 16MB,预留内存 128KB,预留线程 0
  • tuple-ids 是 0,这个能看出各个节点之前的数据传递,行大小 12 字节,行数大概 2.88 百万行
  • 数据流输出给
00:SCAN HDFS [tpcds_parquet.store_sales, RANDOM]
   HDFS partitions=1824/1824 files=1824 size=196.95MB
   stored statistics:
     table: rows=2.88M size=196.95MB
     partitions: 1824/1824 rows=2.88M
     columns: all
   extrapolated-rows=disabled max-scan-range-rows=130.09K
   mem-estimate=16.00MB mem-reservation=128.00KB thread-reservation=0
   tuple-ids=0 row-siz=12B cardinality=2.88M
   in pipelines: 00(GETNEXT)

# 01:AGGREGATE

扫描之后是聚合,这里 STREAMING 说明数据是在扫描过程中聚合的,输出是根据 ss_sold_date_sk 分组之后的行数,这里 spill-buffer 是溢出缓冲区的大小。

01:AGGREGATE [STREAMING]
|  output: sum_init_zero(tpcds_parquet.store_sales.stats: num_rows)
|  group by: ss_sold_date_sk
|  mem-estimate=10.00MB mem-reservation=2.00MB spill-buffer=64.00KB thread-reservation=0
|  tuple-ids=1 row-size=12B cardinality=1.82K
|  in pipelines: 00(GETNEXT)

# F01:PLAN FRAGMENT

每个节点并行扫描并局部聚合之后,就开始根据分组字段哈希分发数据,进行全局聚合操作。

F01:PLAN FRAGMENT [HASH(ss_sold_date_sk)] hosts=3 instances=12
Per-Instance Resources: mem-estimate=10.19MB mem-reservation=1.94MB thread-reservation=1

# 02:EXCHANGE

分发数据。

02:EXCHANGE [HASH(ss_sold_date_sk)]
|  mem-estimate=199.12KB mem-reservation=0B thread-reservation=0
|  tuple-ids=1 row-size=12B cardinality=1.82K
|  in pipelines: 00(GETNEXT)

# 03:AGGREGATE

最终聚合。

03:AGGREGATE [FINALIZE]
|  output: count:merge(*)
|  group by: ss_sold_date_sk
|  mem-estimate=10.00MB mem-reservation=1.94MB spill-buffer=64.00KB thread-reservation=0
|  tuple-ids=1 row-size=12B cardinality=1.82K
|  in pipelines: 03(GETNEXT), 00(OPEN)

# F02:PLAN FRAGMENT

最后一个阶段,合并各个节点的数据到 coordinator。

F02:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1
|  Per-Instance Resources: mem-estimate=199.12KB mem-reservation=0B thread-reservation=1

# 04:EXCHANGE

这次是把数据全部分发到一个节点。

04:EXCHANGE [UNPARTITIONED]
|  mem-estimate=199.12KB mem-reservation=0B thread-reservation=0
|  tuple-ids=1 row-size=12B cardinality=1.82K
|  in pipelines: 03(GETNEXT)

# PLAN-ROOT SINK

输出最终结果。

PLAN-ROOT SINK
|  output exprs: count(*), ss_sold_date_sk
|  mem-estimate=0B mem-reservation=0B thread-reservation=0

# ExecSummary

这部分首先是一些资源预估,然后是整个执行过程的简要总结。

# Estimated Per-Host Mem

每个节点预估使用内存。

Estimated Per-Host Mem: 152014464

# Request Pool

使用的资源池。

Request Pool: default-pool

# Per Host Min Memory Reservation

每个节点最小内存剩余。

Per Host Min Memory Reservation: tarmstrong-Precision-7540:27002(16.25 MB) tarmstrong-Precision-7540:27000(16.25 MB) tarmstrong-Precision-7540:27001(16.25 MB)

# Per Host Number of Fragment Instances

每个节点的查询片段实例数,上面是总共 3 个查询片段,前两个每个节点并行 4 个,最后一个汇总结果所以只能 1 个。

Per Host Number of Fragment Instances: tarmstrong-Precision-7540:27002(8) tarmstrong-Precision-7540:27000(9) tarmstrong-Precision-7540:27001(8)

# Admission result

准入情况。

Admission result: Admitted immediately

# Cluster Memory Admitted

整个集群中允许使用的内存大小,这个是在查询准入之后的内存。

Cluster Memory Admitted: 434.92 MB

# Executor Group

Executor 所属的组。

Executor Group: default

# ExecSummary

这个能看出来各个阶段的耗时、行数、内存等情况。

Operator              #Hosts  #Inst   Avg Time  Max Time  #Rows  Est. #Rows   Peak Mem  Est. Peak Mem  Detail                    
F02:ROOT                   1      1    3.999ms   3.999ms                             0              0                            
04:EXCHANGE                1      1    3.999ms   3.999ms  1.82K       1.82K    1.19 MB      199.12 KB  UNPARTITIONED             
F01:EXCHANGE SENDER        3     12  333.329us   3.999ms                       9.84 KB              0                            
03:AGGREGATE               3     12    4.333ms  11.999ms  1.82K       1.82K    2.15 MB       10.00 MB  FINALIZE                  
02:EXCHANGE                3     12  333.329us   3.999ms  1.82K       1.82K  112.00 KB      199.12 KB  HASH(ss_sold_date_sk)     
F00:EXCHANGE SENDER        3     12    1.666ms   3.999ms                     166.12 KB              0                            
01:AGGREGATE               3     12    5.999ms  11.999ms  1.82K       1.82K    2.02 MB       10.00 MB  STREAMING                 
00:SCAN HDFS               3     12    1s017ms   1s023ms  1.82K       2.88M  132.00 KB       16.00 MB  tpcds_parquet.store_sales

# Query Compilation

编译阶段花费 284.14ms

  • 缓存元数据
  • 分析
  • 鉴权
  • 计算值传递图
  • 创建单节点计划
  • 计算 runtime filter
  • 创建分布式计划
  • 创建并行计划
  • 完成计划
Query Compilation: 284.144ms
   - Metadata of all 1 tables cached: 5.857ms (5.857ms)
   - Analysis finished: 17.866ms (12.009ms)
   - Authorization finished (noop): 18.208ms (341.943us)
   - Value transfer graph computed: 34.199ms (15.991ms)
   - Single node plan created: 189.134ms (154.934ms)
   - Runtime filters computed: 194.459ms (5.324ms)
   - Distributed plan created: 195.676ms (1.217ms)
   - Parallel plans created: 198.019ms (2.342ms)
   - Planning finished: 284.144ms (86.125ms)

# Query Timeline

查询阶段耗时

  • 提交查询
  • 生成执行计划
  • 提交准入
  • 准入完成
  • be 开始执行
  • be 执行完成
  • 生成查询结果
  • 客户端拉取第一行数据
  • 客户端拉取最后一行数据
  • 释放准入控制资源
  • 取消注册查询
Query Timeline: 1s547ms
   - Query submitted: 0.000ns (0.000ns)
   - Planning finished: 311.996ms (311.996ms)
   - Submit for admission: 311.996ms (0.000ns)
   - Completed admission: 327.996ms (15.999ms)
   - Ready to start on 3 backends: 327.996ms (0.000ns)
   - All 3 execution backends (25 fragment instances) started: 343.996ms (15.999ms)
   - Rows available: 1s515ms (1s171ms)
   - First row fetched: 1s523ms (7.999ms)
   - Last row fetched: 1s531ms (7.999ms)
   - Released admission control resources: 1s547ms (15.999ms)
   - Unregister query: 1s547ms (0.000ns)

# 其他耗时

  • 上次更新准入控制时间,用于监测 Admission Control 的活动
  • 计算和分配扫描范围
  • 查询处于非活动状态的时间
  • 查询总耗时,这个不知道为什么是零
- AdmissionControlTimeSinceLastUpdate: 80.000ms
- ComputeScanRangeAssignmentTimer: 15.999ms
- InactiveTotalTime: 0.000ns
- TotalTime: 0.000ns

# Frontend

这两个耗时也都是零,不知道为什么。

- InactiveTotalTime: 0.000ns
- TotalTime: 0.000ns

# ImpalaServer

  • 客户端拉取数据时的等待时间
  • 查询处于非活动状态的时间
  • 客户端拉取的数据行数
  • 客户端从缓存拉取的数据行数
  • 表示在查询结果中每秒生成的行数。这个指标用于衡量查询在将结果行从计算产生到最终呈现的速度。
  • 表示查询在生成结果行时所花费的总时间。这个指标包括了将计算产生的结果行实际生成和准备好以供输出的时间。
  • 总耗时
ImpalaServer:
   - ClientFetchWaitTimer: 0.000ns
   - InactiveTotalTime: 0.000ns
   - NumRowsFetched: 1.82K (1824)
   - NumRowsFetchedFromCache: 0 (0)
   - RowMaterializationRate: 57.00 K/sec
   - RowMaterializationTimer: 31.999ms
   - TotalTime: 0.000ns

# 总结

关于每个执行节点的详细情况,在下面中进行分析。