一步一步理解Impala query profile(二)

  • 2019 年 12 月 16 日
  • 筆記

作者:Eric Lin (林晨輝), Cloudera高級售後技術支援工程師。畢業於Monash大學電腦科學, Sir John Monash的獎學金獲得者。曾就業於數據收集公司如Hitwise(現為Experian的子公司)和Effective Measure,擔任高級工程師,負責設計,開發和管理用於採集, 處理和報告網路數據的平台(基於PHP,Java和CDH)。現任職Cloudera, 擔任高級售後技術支援工程師,主要擅長解決在CDH生態系統中出現的各種疑難雜症。

在上一篇文章《一步一步理解Impala query profile(一)》中,我們介紹了Impala query profie的概要部分,在本篇文章我們介紹Profile的查詢計劃(Query Plan)和執行概要(Execution Summary)部分。

Profile的查詢計劃和執行概要如下所示:

Query (id=36433472787e1cab:29c30e7800000000):    Summary:      ....Skipped here....      Plan:  ----------------  Max Per-Host Resource Reservation: Memory=0B  Per-Host Resource Estimates: Memory=52.00MB  WARNING: The following tables are missing relevant table and/or column statistics.  default.sample_07    F01:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1  |  Per-Host Resources: mem-estimate=10.00MB mem-reservation=0B  PLAN-ROOT SINK  |  mem-estimate=0B mem-reservation=0B  |  03:AGGREGATE [FINALIZE]  |  output: count:merge(*)  |  mem-estimate=10.00MB mem-reservation=0B spill-buffer=2.00MB  |  tuple-ids=1 row-size=8B cardinality=1  |  02:EXCHANGE [UNPARTITIONED]  |  mem-estimate=0B mem-reservation=0B  |  tuple-ids=1 row-size=8B cardinality=1  |  F00:PLAN FRAGMENT [RANDOM] hosts=1 instances=1  Per-Host Resources: mem-estimate=42.00MB mem-reservation=0B  01:AGGREGATE  |  output: count(*)  |  mem-estimate=10.00MB mem-reservation=0B spill-buffer=2.00MB  |  tuple-ids=1 row-size=8B cardinality=1  |  00:SCAN HDFS [default.sample_07, RANDOM]     partitions=1/1 files=1 size=44.98KB     stats-rows=unavailable extrapolated-rows=disabled     table stats: rows=unavailable size=44.98KB     column stats: all     mem-estimate=32.00MB mem-reservation=0B     tuple-ids=0 row-size=0B cardinality=unavailable  ----------------      Estimated Per-Host Mem: 54525952      Tables Missing Stats: default.sample_07      Per Host Min Reservation: nightly514-3.vpc.cloudera.com:22000(0) nightly514-4.vpc.cloudera.com:22000(0)      Request Pool: root.hive      Admission result: Admitted immediately      ExecSummary:  Operator       Hosts   Avg Time   Max Time  #Rows  Est. #Rows  Peak Mem  Est. Peak Mem  Detail  -----------------------------------------------------------------------------------------------------------  03:AGGREGATE        1    0.000ns    0.000ns      1           1  20.00 KB       10.00 MB  FINALIZE  02:EXCHANGE         1  868.991ms  868.991ms      1           1         0              0  UNPARTITIONED  01:AGGREGATE        1    0.000ns    0.000ns      1           1  16.00 KB       10.00 MB  00:SCAN HDFS        1  743.001ms  743.001ms    823          -1  80.00 KB       32.00 MB  default.sample_07  

接下來我們來逐一提取和介紹上面Profile片段中的資訊:

1、表/列統計資訊:

Max Per-Host Resource Reservation: Memory=0B  Per-Host Resource Estimates: Memory=52.00MB  WARNING: The following tables are missing relevant table and/or column statistics.  default.sample_07  

但是,下一行非常重要,因為Impala告訴我們是否檢測到查詢所涉及的表具有最新的統計資訊,這一點非常關鍵,因為Impala使用表/列統計資訊(table/column statistics information)來進行資源預估(resource estimation),並執行查詢計劃來確定運行查詢的最佳策略,如果統計資訊不是最新的,Impala最終將使用錯誤的查詢計劃,從而影響整體查詢性能。

在上面的示例中,我們可以看到default.sample_07表缺少統計資訊,Impala在查詢計劃中給出了警告來提示用戶需要在該表上執行COMPUTE STATS來消除這個警告資訊。關於表統計的更多資訊,請參閱Table and Column Statistics。

https://www.cloudera.com/documentation/enterprise/latest/topics/impala_perf_stats.html

2、查詢計劃詳情:

F01:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1  |  Per-Host Resources: mem-estimate=10.00MB mem-reservation=0B  PLAN-ROOT SINK  |  mem-estimate=0B mem-reservation=0B  |  03:AGGREGATE [FINALIZE]  |  output: count:merge(*)  |  mem-estimate=10.00MB mem-reservation=0B spill-buffer=2.00MB  |  tuple-ids=1 row-size=8B cardinality=1  |  02:EXCHANGE [UNPARTITIONED]  |  mem-estimate=0B mem-reservation=0B  |  tuple-ids=1 row-size=8B cardinality=1  |  F00:PLAN FRAGMENT [RANDOM] hosts=1 instances=1  Per-Host Resources: mem-estimate=42.00MB mem-reservation=0B  01:AGGREGATE  |  output: count(*)  |  mem-estimate=10.00MB mem-reservation=0B spill-buffer=2.00MB  |  tuple-ids=1 row-size=8B cardinality=1  |  00:SCAN HDFS [default.sample_07, RANDOM]     partitions=1/1 files=1 size=44.98KB     stats-rows=unavailable extrapolated-rows=disabled     table stats: rows=unavailable size=44.98KB     column stats: all     mem-estimate=32.00MB mem-reservation=0B     tuple-ids=0 row-size=0B cardinality=unavailable  

查詢計劃(Query plan)是Impala profile中最重要的部分之一,我們需要知道如何讀取它,因為它告訴我們如何掃描(scan)表、交換數據(data exchange)和連接(join)以獲得最終結果。

如果查詢很複雜,查詢計劃也可能會變得非常複雜,讓我們從這個簡單的查詢開始,以了解它的基本資訊。需要記住的一件事是,我們需要反向閱讀這些資訊,來理解Impala的執行計劃。

2.1、HDFS 掃描:

第一步通常從HDFS掃描(HDFS Scan)開始:

00:SCAN HDFS [default.sample_07, RANDOM]     partitions=1/1 files=1 size=44.98KB     stats-rows=unavailable extrapolated-rows=disabled     table stats: rows=unavailable size=44.98KB     column stats: all     mem-estimate=32.00MB mem-reservation=0B     tuple-ids=0 row-size=0B cardinality=unavailable  

從上面的片段中我們可以獲取下面這些有用的資訊:

  • 表中只有一個分區,Impala也讀取一個分區。這並不一定意味著這個表是分區的,如果表沒有分區,它也將顯示為1/1
  • 表/分區下只有一個文件(files=1)
  • Impala讀取的數據總大小為44.98KB
  • 這個表沒有可用的統計資訊(stats-rows=unavailable, table stats: rows=unavailable, cardinality=unavailable)
  • 運行查詢所需的記憶體估計值為32MB,沒有記憶體被預留

2.2、Aggregation操作:

HDFS掃描完成後,Impala需要做聚合(Aggregation),因為我們的SQL語句中使用了COUNT(*):

01:AGGREGATE  |  output: count(*)  |  mem-estimate=10.00MB mem-reservation=0B spill-buffer=2.00MB  |  tuple-ids=1 row-size=8B cardinality=1  

這裡沒有太多要解釋的,這個步驟執行的是聚合操作。

2.3、Fragment資訊:

F00:PLAN FRAGMENT [RANDOM] hosts=1 instances=1  Per-Host Resources: mem-estimate=42.00MB mem-reservation=0B  

00:SCAN HDFS和01:AGGREGATE片段上的SCAN和Aggregation操作都屬於片段(FRAGMENT)F00,它在一個主機和一個實例上運行。F00這個片段ID可以用來在Profile的後面部分找到實際的片段統計資訊,它可以告訴我們這個片段在運行時如何運行的詳細資訊。我們還將在本系列的後面部分討論這個問題。

2.4、Exchange操作:

02:EXCHANGE [UNPARTITIONED]  |  mem-estimate=0B mem-reservation=0B  |  tuple-ids=1 row-size=8B cardinality=1  

在每個工作節點(worker node)上完成聚合之後,需要將每個工作節點的結果交換給協調器節點(coordinator),這個步驟主要做的是這個操作,之後,協調器節點需要對這些結果進行最後的匯總/合併(aggregation/merger):

03:AGGREGATE [FINALIZE]  |  output: count:merge(*)  |  mem-estimate=10.00MB mem-reservation=0B spill-buffer=2.00MB  |  tuple-ids=1 row-size=8B cardinality=1  

以上兩個操作都屬於同一個片段01,該片段又可以用來引用Profile數據的其餘部分,以獲取關於查詢的更詳細的統計資訊:

F01:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1  

現在,讓我們來看看Profile的執行概要部分:

Operator       #Hosts   Avg Time   Max Time  #Rows  Est. #Rows  Peak Mem  Est. Peak Mem  Detail  -----------------------------------------------------------------------------------------------------------  03:AGGREGATE        1  999.992us  999.992us      1           1  20.00 KB       10.00 MB  FINALIZE  02:EXCHANGE         1  831.992ms  831.992ms      1           1         0              0  UNPARTITIONED  01:AGGREGATE        1    0.000ns    0.000ns      1           1  16.00 KB       10.00 MB  00:SCAN HDFS        1  709.995ms  709.995ms    823          -1  80.00 KB       32.00 MB  default.sample_07  

在這裡你可以找到這些有用的資訊:

  • 每個操作花費的平均時間(Avg Time)和最大時間(Max Time):如果兩者相差較大,我們就會知道每個worker節點運行作業時存在不平衡/傾斜(in-balance/skew)情況,從理論上講,它們應該處理相同數量的數據,所有節點應該在相同的時間範圍內完成任務
  • 實際行數和估計行數:#Row表示運行查詢後實際返回的行數,Est. #Rows表示Impala根據表統計數據計算出的估計行數。如果#Row和Est. #Rows相差較大,就表明Impala中的表統計資訊已經過時。在案例中,SCAN HDFS操作的Est. #Rows值為-1,#Rows的值為823,就我們的測試表而言,我們沒有表統計資訊,因此Impala報告了-1的估算值。如果估計值(estimated value)是正數,但仍與實際返回的行數不同,我們就需要對該表運行COMPUTE STATS以更新統計資訊
  • 參與查詢操作的節點數量:#Hosts列告訴我們,有多少工作節點參與了查詢中的相關操作。在我的例子中,由於數據很小,我們只有一個主機來運行查詢
  • 實際記憶體和估計記憶體:Peak Mem和Est. Peak Mem是不言自明的,它們表示實際使用的記憶體與Impala根據表統計數據計算出的估計記憶體

如果查詢中有連接(join)操作,Profile的總結資訊中還將向我們展示連接操作中使用了什麼連接策略:廣播連接(Broadcast Join)還是隨機連接(Shuffle Join)。在本系列的最後一部分,我將用一個更複雜的query profile讓大家了解更多資訊。

英文以及中文翻譯原文如下:

https://www.ericlin.me/2018/09/impala-query-profile-explained-part-1/  https://my.oschina.net/dabird/blog/3138768

Tags: