一步一步理解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

