hive執行計划解析
Hive wiki - LanguageManual Explain
1.hive執行流程的重要性
1)當sql任務非常慢時,就需要分析它的執行流程
2)常見的面試中,問對hive的理解?回答只是寫sql,這個是很片面的。要從表面的sql,在腦海中映射出MR流程,在哪兒進行map,combiner,shuffle,reduce
2.解析sql執行計划流程
2.1 大數據兩類sql框架
單表分析:select a,聚合函數 from XXX group by b
多表join分析:select a.,b. from a join b on a.id=b.id
這兩種sql框架,概括了所有的大數據sql,幾乎不可能有第三種寫法,區別可能是業務復雜,寫的復雜點兒而已。
2.2 解析sql執行計划流程詳解
1)parser:將sql解析為AST(抽象語法樹),會進行語法校驗,AST本質* * 還是字符串
2)Analyzer:語法分析,生成QB(query block)
3)Logicl Plan:邏輯執行計划解析,生成一堆Opertator Tree
4)Logicl Optimizer:進行邏輯執行計划優化,生成一堆Opertator Tree
5)Phsical plan:物理執行計划解析,生成 tasktree
6)Phsical Optimizer:進行物理執行計划優化,生成 t優化后tasktree,該任務即是在集群上執行的作業 任務
六步將普通的sql映射成了作業任務。重點是 邏輯執行計划優化和物理執行計划優化
3.sql執行計划映射MR流程
3.1過濾類查詢sql
select a.id,a,city, a.cate form access a where a.day=’20190414’ and a.cate= ‘奔馳’
整個job是沒有reduce的,類似etl作業。其中map數是由文件分片數決定。分區條件直接在數據讀取時過濾
3.2分組聚合類查詢sql
select city, count(1) form access a where a.day=’20190414’ and a.cate= ‘奔馳’ group by city
和WC的流程沒有本質區別,如上圖combiner是本地局部的redece,好處是減少shuffle的數據量,但不是任何場景都會發生combiner,如求平均數。
3.3join類查詢sql
待補充
4. 執行計划優化
待補充
擴展1: reducebykey和groupbykey的區別,前者會發生combiner 局部聚合,而后者不會,前者獲得的是相同key對應的一個元素,后者是獲取元素集合。reducebykey更加適合大數據,少用groupbykey(全數據shuffle)
擴展2: map task數是由數據文件分片數決定的分片數即是map任務數,程序員只能給個期望值
擴展3: reduce task數是由輸入reduce的數據的分區(partitions)數決定的即分區數為map任務數,默認是1,程序員可直接設置reduce個數來改變reduce task數,reduce task數決定來 生成的文件數。
擴展4: MR數據shuffle確定數據發往哪一個reduce分區的規則是:取key的hashcode值對分區數模。
擴展5: explain sql ;查看某sql語句的執行計划
來源於:https://blog.csdn.net/weixin_42921390/article/details/115289415?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control
===========================================================================================================================================================================================================================================================================
explain select s0.sno,count(distinct s0.sname) from student s0 left outer join student1 s1 on (s0.sno=s1.sno) group by s0.sno;
這里有兩張表,一個student表,一個student1表。兩個表的sno,做一個join操作。並且對 sno進行分組,然后將分組完成之后的表達式中的sname不同的條數統計出來。
下面我們執行這個解釋語句,執行的結果如下:
STAGE DEPENDENCIES:
Stage-5 is a root stage
Stage-2 depends on stages: Stage-5
Stage-0 depends on stages: Stage-2
--這里將整個的語句划分為三個階段,Stage-5作為根目錄,然后Stage-2是對Stage-5的依賴。最后Stage-0將結果顯示出來
STAGE PLANS:
Stage: Stage-5
Map Reduce Local Work
Alias -> Map Local Tables:
s1 --這里先進行第一次的map,然后這里將第二張表的表名加載進來,標記別名。這里進行的Fetch 操作。
Fetch Operator
limit: -1
Alias -> Map Local Operator Tree: --這里是本地的map 操作加載數據。
s1
TableScan
alias: s1
Statistics: Num rows: 40 Data size: 160 Basic stats: COMPLETE Column stats: NONE
HashTable Sink Operator --這里進行的hash操作。下面是條件表達式。
condition expressions:
0 {sno} {sname}
1
keys:
0 sno (type: int)
1 sno (type: int)
Stage: Stage-2 --然后進入到第二階段。在這個階段才是真正的map reduce階段。
Map Reduce
Map Operator Tree: --這里進行的map操作。
TableScan --首先掃描坐標的表。
alias: s0
Statistics: Num rows: 3 Data size: 320 Basic stats: COMPLETE Column stats: NONE
Map Join Operator --這里采用的hive吧這條sql解釋為了map join。
condition map:
Left Outer Join0 to 1 --這里進行連接。將左表和右表進行連接。
condition expressions:
0 {sno} {sname}
1
keys:
0 sno (type: int)
1 sno (type: int)
outputColumnNames: _col0, _col1 --這里輸出兩列。分別是sno,sname。
Statistics: Num rows: 44 Data size: 176 Basic stats: COMPLETE Column stats: NONE
Select Operator --在這里執行了一次select操作。
expressions: _col0 (type: int), _col1 (type: string)
outputColumnNames: _col0, _col1
Statistics: Num rows: 44 Data size: 176 Basic stats: COMPLETE Column stats: NONE
Group By Operator --在hive當中,為了優化sql,在數據進入到reduce端之前,會對數據進行簡單的分組。在這里將分組的sno和sname,作為健,輸出的三個列的數據。
aggregations: count(DISTINCT _col1)
keys: _col0 (type: int), _col1 (type: string)
mode: hash
outputColumnNames: _col0, _col1, _col2 --這里進行三個列的輸出對於這 _col2,我的理解是兩個列組成的和。
Statistics: Num rows: 44 Data size: 176 Basic stats: COMPLETE Column stats: NONE
Reduce Output Operator --在這里我們可以看到在進入到reduce之前,需要進行一些操作。
key expressions: _col0 (type: int), _col1 (type: string)
sort order: ++ --這里對數據進行分組排序,也是shuffle過程的前期准備。對同一個map task端的數據進行排序。
Map-reduce partition columns: _col0 (type: int) --這里將對map出的數據進行分組,這里是將數據按照group by的列名稱進行分作輸送到不同的partition當中。
Statistics: Num rows: 44 Data size: 176 Basic stats: COMPLETE Column stats: NONE
Local Work:
Map Reduce Local Work
Reduce Operator Tree: --在這里我們的數據進入到reduce階段的處理。
Group By Operator --在這里才是正真的分組。
aggregations: count(DISTINCT KEY._col1:0._col0) --然后我們將各個組當中的數據按照我們分好的組,然后統計這個組當中不同的sname的數量。
keys: KEY._col0 (type: int)
mode: mergepartial
outputColumnNames: _col0, _col1 --這里將統計的好書進行輸出。
Statistics: Num rows: 22 Data size: 88 Basic stats: COMPLETE Column stats: NONE
Select Operator
expressions: _col0 (type: int), _col1 (type: bigint)
outputColumnNames: _col0, _col1
Statistics: Num rows: 22 Data size: 88 Basic stats: COMPLETE Column stats: NONE
File Output Operator --這里是文件的數據操作,也是落地到磁盤的操作。
compressed: false
Statistics: Num rows: 22 Data size: 88 Basic stats: COMPLETE Column stats: NONE
table:
input format: org.apache.hadoop.mapred.TextInputFormat --這個是讀入數據的操作。
output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat --這個是輸出數據的格式。
serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
Stage: Stage-0 --在這個階段我們對剛才處理的數據進行展示處理。
Fetch Operator
limit: -1
Processor Tree:
ListSink
其實這里我們看到數據寫磁盤的操作。在map完了之后的階段。可能是因為數據量不夠大的緣故吧。
另外這里采用的是map jion的操作也沒有看到在join的時候,出現shuffle的過程。我覺得可能也是數據量太小了吧。直接加載進了分布式緩存當中。才造成現在的現象。
轉自:https://www.cnblogs.com/gxgd/p/9463129.html
==================================================================================================================================================================================
數據傾斜時學習hive sql執行計划 Hive sql的一段執行計划 STAGE DEPENDENCIES: Stage-1 is a root stage Stage-6 depends on stages: Stage-1, Stage-3 , consists of Stage-7, Stage-8, Stage-2 Stage-7 has a backup stage: Stage-2 Stage-4 depends on stages: Stage-7 Stage-8 has a backup stage: Stage-2 Stage-5 depends on stages: Stage-8 Stage-2 Stage-3 is a root stage Stage-0 depends on stages: Stage-4, Stage-5, Stage-2 一個stage對應一個mapreduce的作業 is a root stage 表示不依賴任何的stage,多個root stage的sql可以開啟並行執行 depends on stages 表示依賴的stages必須執行完成之后才能執行 consists of Stage-7, Stage-8, Stage-2 表示的是其中一個stage滿足即可。 Stage-7 has a backup stage: Stage-2 表示優先執行stage-7,如果stage-7不滿足執行的要求,將會執行stage-2。比如map join的情況,如果小表的大小小於hive.mapjoin.smalltable.filesize小表閾值, 默認為25M,單位byte。就會執行stage-7,如果小表的大小大於小表閾值,將會執行stage-2的mapreduce。結果一樣,但是性能會差很多。 join的一些調優參數 --是否自動轉換為mapjoin,發生map join可以看到執行的stage對應的執行計划是map local task。而不是mapreduce。map join是將小表加載到內存,然后序列化到磁盤放到hdfs,然后放到所有的節點進行join set hive.auto.convert.join = true; --小表的最大文件大小,默認為25000000,即25M set hive.mapjoin.smalltable.filesize = 25000000; --是否將多個mapjoin合並為一個,針對的是連續多個join。多個join的小表都滿足map join的時候可以合並,通過閾值判斷合並哪幾個還是全部map join合並。 set hive.auto.convert.join.noconditionaltask = true; --多個mapjoin轉換為1個時,所有小表的文件大小總和的最大值。如果有兩個的和小於閾值,就合並兩個,靈活合並map jion set hive.auto.convert.join.noconditionaltask.size = 10000000; 問題: 20210310遇到的數據傾斜問題,3個left join耗時1小時, 事實表數據量70G。 搜索點擊數據事實表(數據量比較大)join 搜索關鍵字的分詞維度表 using 搜索關鍵字 使用搜索關鍵字當做key在map-reduce進行hash分區,熱門的搜索詞搜索的記錄比較多,這樣就會導致數據傾斜。 處理方式 先統計搜索點擊事實表中的搜索詞有沒有為null和''的,統計數量,避免空值導致的數據傾斜。 結果:沒有空值的搜索詞 判斷join的分詞維度表是不是小表,查看后發現大小為140M,設置hive.mapjoin.smalltable.filesize大於140M, 結果:執行任務,查看stage的執行情況,發現執行了map local task。而不是mapreduce任務。(查看方法:對比日志中執行的stage和執行計划中的stage就能發現執行的是map local task,而不是mapreduce)。3個left join的sql耗時縮短為30分鍾。 繼續優化 將多個map join進行合並(也就是將3個left join的map join進行合並)。待補充。
轉自:https://www.cnblogs.com/jeasonchen001/p/14514782.html