Improvements to the Hive Optimizer,improvementshive
LanguageManual JoinOptimization
Improvementsto the Hive Optimizer
Hive可以自動最佳化,在Hive 0.11裡面改進了一些最佳化用例
1、 JOIN的一邊適合放在記憶體,有新的最佳化方案
a) 把表按照hash表的形式讀進記憶體
b) 只掃描大表
c) fact表只使用少量記憶體
2、 星型join
3、 在很多情況下,不再需要hint
4、 Map Join自動最佳化
StarJoin Optimization
先介紹一下星型模型和雪花型模型
===================開始=======================
1、簡介
星形模式是一種多維的資料關係,它由一個事實表(FactTable)和一組維表(Dimension Table)組成。每個維表都有一個維作為主鍵,所有這些維的主鍵組合成事實表的主鍵。事實表的非主鍵屬性稱為事實(Fact),它們一般都是數值或其他可以進行計算的資料;而維大都是文字、時間等類型的資料,按這種方式組織好資料我們就可以按照不同的維(事實表主鍵的部分或全部)來對這些事實資料進行求和(summary)、求平均(average)、計數(count)、百分比(percent)的聚集計算,甚至可以做20~80分析。這樣就可以從不同的角度數字來分析業務主題的情況。
在多維分析的商業智慧解決方案中,根據事實表和維度資料表的關係,又可將常見的模型分為星型模型和雪花型模型。在設計邏輯型資料的模型的時候,就應考慮資料是按照星型模型還是雪花型模型進行組織。
當所有維表都直接連接到“ 事實表”上時,整個圖解就像星星一樣,故將該模型稱為星型模型, 2 。
星型結構描述是一種非正規化的結構,Cube的每一個維度都直接與事實表相串連,不存在漸層維度,所以資料有一定的冗餘,如在地區維度資料表中,存在國家 A 省 B 的城市 C 以及國家 A 省 B 的城市 D 兩條記錄,那麼國家 A 和省 B 的資訊分別儲存了兩次,即存在冗餘。
為銷售資料倉儲中的星型模型:
當有一個或多個維表沒有直接連接到事實表上,而是通過其他維表串連到事實表上時,其圖解就像多個雪花串連在一起,故稱雪花模型。雪花模型是對星型模型的擴充。它對星型模型的維表進一步層次化,原有的各維表可能被擴充為小的事實表,形成一些局部的 " 層次 " 地區,這些被分解的表都串連到主要維度資料表而不是事實表。 2,將地區維表又分解為國家,省份,城市等維表。它的優點是 : 通過最大限度地減少資料存放區量以及聯合較小的維表來改善查詢效能。雪花型結構去除了資料冗餘。
為銷售資料倉儲中的雪花型模型:
星型模型因為資料的冗餘所以很多統計查詢不需要做外部的串連,因此一般情況下效率比雪花型模型要高。星型結構不用考慮很多正規化的因素,設計與實現都比較簡單。雪花型模型由於去除了冗餘,有些統計就需要通過表的聯結才能產生,所以效率不一定有星型模型高。正規化也是一種比較複雜的過程,相應的資料庫結構設計、資料的 ETL、以及後期的維護都要複雜一些。因此在冗餘可以接受的前提下,實際運用中星型模型使用更多,也更有效率。
2、使用選擇
星形模型(StarSchema)和雪花模型(SnowflakeSchema)是資料倉儲中常用到的兩種方式,而它們之間的對比要從四個角度來進行討論。
1)資料最佳化
雪花模型使用的是正常化資料,也就是說資料在資料庫內部是組織好的,以便消除冗餘,因此它能夠有效地減少資料量。通過參考完整性,其業務層級和維度都將儲存在資料模型之中。
▲圖1 雪花模型
相比較而言,星形模型實用的是反正常化資料。在星形模型中,維度直接指的是事實表,業務層級不會通過維度之間的參照完整性來部署。
▲圖2 星形模型
2)業務模型
主鍵是一個單獨的唯一鍵(資料屬性),為特殊資料所選擇。在上面的例子中,Advertiser_ID就將是一個主鍵。外鍵(參考屬性)僅僅是一個表中的欄位,用來匹配其他維度資料表中的主鍵。在我們所引用的例子中,Advertiser_ID將是Account_dimension的一個外鍵。
在雪花模型中,資料模型的業務層級是由一個不同維度資料表主鍵-外鍵的關係來代表的。而在星形模型中,所有必要的維度資料表在事實表中都只擁有外鍵。
3)效能
第三個區別在於效能的不同。雪花模型在維度資料表、事實表之間的串連很多,因此效能方面會比較低。舉個例子,如果你想要知道Advertiser 的詳細資料,雪花模型就會請求許多資訊,比如AdvertiserName、ID以及那些廣告主和客戶表的地址需要串連起來,然後再與事實表串連。
而星形模型的串連就少的多,在這個模型中,如果你需要上述資訊,你只要將Advertiser的維度資料表和事實表串連即可。
4)ETL
雪花模型載入資料集市,因此ETL操作在設計上更加複雜,而且由於附屬模型的限制,不能並行化。
星形模型載入維度資料表,不需要再維度之間添加附屬模型,因此ETL就相對簡單,而且可以實現高度的並行化。
總結
雪花模型使得維度分析更加容易,比如“針對特定的廣告主,有哪些客戶或者公司是線上的?”星形模型用來做指標分析更適合,比如“給定的一個客戶他們的收入是多少?”
===================結束=======================
在決策支援系統或者資料倉儲中,一個簡單的模式是星型模式,事件都是儲存在大的事實表(facttables)裡面的,很多小的維表(dimensions)來描述事實表中的資料。
TPC DS就是星型模式中的一個例子。
1、StarSchema Example
Selectcount(*) cnt
Fromstore_sales ss
join household_demographics hd on(ss.ss_hdemo_sk = hd.hd_demo_sk)
join time_dim t on (ss.ss_sold_time_sk =t.t_time_sk)
join store s on (s.s_store_sk =ss.ss_store_sk)
Where
t.t_hour = 8
t.t_minute >= 30
hd.hd_dep_count = 2
order by cnt;
2、PriorSupport for MAPJOIN
Hive支援MAPJOINS,很適合這個方案-至少對於dimensions小到足夠放到記憶體。
在Hive 0.11之前,hive.auto.convert.join預設值為false,如果需要使用MAPJOIN,則使用最佳化器hint方式:
select/*+ MAPJOIN(time_dim) */ count(*) from
store_sales join time_dimon (ss_sold_time_sk = t_time_sk);
或者通過設定參數後自動進行mapjoin:
sethive.auto.convert.join=true;
selectcount(*) from
store_sales join time_dimon (ss_sold_time_sk = t_time_sk);
在Hive 0.11.0開始,hive.auto.convert.join預設值為true。
MAPJOINS把小表hash map的形式讀進記憶體,然後和大表匹配key,以下是各階段的分工:
1) Localwork:本地
•readrecords via standard table scan (including filters and projections) from sourceon local machine --------掃描表
•buildhashtable in memory -------在記憶體中建立hash表
•writehashtable to local disk --------hash表寫進本地磁碟
•uploadhashtable to dfs -----------上傳hash表到hdfs
•add hashtable to distributed cache --------把hash表加進分布式緩衝
2) Maptask:Map任務
•readhashtable from local disk (distributed cache) into memory ------從本地磁碟(分布式緩衝)把hash表讀進記憶體
•matchrecords' keys against hashtable --------與hash表匹配key
•combine matches and write to output --------合并匹配,並寫出output
3) Noreduce task:MapJoin特點,沒有reduce
Limitationsof Prior Implementation
MAPJOIN在Hive 0.11之前有如下的一些限制:
1) 一個mapjoin只能一次處理一個key,它可以執行多表串連,但只有當所有的表都加入了相同的key。(典型的星型串連不屬於這一類)
2) 就算是加了hint也未必真的使用mapjoin。
3) 一連串的mapjoins不會合并成一個單一的map job,除非查詢寫成一個級聯的mapjoin(mapjoin(table,subquery(mapjoin(table, subquery....).自動轉換後的也不會變成一個單一的map job。
4) mapjoin中用到的雜湊表,每個子QUERY運行都會產生,先下載,再分發給map。
Enhancementsfor Star Joins
調優主要從三方面入手的:
1) 使用MapJoinHint時,把一連串的MapJoin操作變成一個map-only的job。
2) 把最佳化方案儘可能的變成自動最佳化(順便備份下執行計畫)。
3) 使得hashtable在taskside(map端)直接產生,現在的方案是先在本地產生,然後傳到HDFS,再分布式緩衝去分給每個map,未來版本會實現。
下面部分將描述每個最佳化加強方面:
OptimizeChains of Map Joins
下面的SQL會被分解為2個獨立的map-only jobs執行:
select/*+ MAPJOIN(time_dim, date_dim) */ count(*) from
store_sales
jointime_dim on (ss_sold_time_sk = t_time_sk)
joindate_dim on (ss_sold_date_sk = d_date_sk)
where t_hour = 8 andd_year = 2002;
將小表讀進記憶體,如果fact唯讀了一次,而不是2次,那麼會極大的減少執行時間。
Current and Future Optimizations當前和未來調優的方向
1) MergeM*-MR patterns into a single MR. ----把多個map-only的job+MRjob的模式變成單個MR
2) MergeMJ->MJ into a single MJ when possible. -----儘可能的把mapjoin嵌套模式變成一個mapjoin
3) Merge MJ* patterns intoa single Map stage as a chain of MJ operators. (Not yet implemented.) ------------把多個mapjoin串起來,變成一連串的mapjoin(上面的例子是分成兩個獨立的map-only的job,而不是一連串的,功能暫未實現)
如果hive.auto.convert.join為true的話,不僅僅會將join轉化為mapjoin,還有可能轉化成MJ*這種模式。
OptimizeAuto Join Conversion
當auto join開啟時,就不再需要使用hint了,參數有兩個:
sethive.auto.convert.join.noconditionaltask = true;
Hive0.11.0開始預設為true
sethive.auto.convert.join.noconditionaltask.size = 10000000;
小於這個size的表被放入記憶體,這個size大小指的是被放進記憶體的hash表的大小總和,目前的版本,n-1個表都可以被放進記憶體,最大的那個表放在磁碟上match。在這裡不會去檢查表是否被壓縮,直接從HDFS中得到的file大小。
之前的例子就可以變成:
selectcount(*) from
store_sales
jointime_dim on (ss_sold_time_sk = t_time_sk)
joindate_dim on (ss_sold_date_sk = d_date_sk)
where t_hour = 8 andd_year = 2002;
如果這2個維表的大小符合config的size,就會轉換成map-join(2個).。這裡的size 我認為應該是指hive.smalltable.filesize 這個值 預設25m。
如果維表的總和小於noconditionaltask.size 會把2個map-join 合并成一個。這樣做減少了MR job的數量,並顯著提高了query的速度。.這個例子可以很容易地擴充為muti-way join 以及將按預期工作。
外串連不能用map-join。因為map-join 只能有一個steam表,steam表的所有column都應該是全的,外串連可能出現null。
這意味著外串連不能用,只有內串連才能map-join。外串連只能用stream table的形式來調優了。笛卡爾積就更別說了,無法使用map-jon。
自動開關也可以作用在sort-merge-bucketjoins
CurrentOptimization 當前的最佳化方案
把多個MJ合并成一個MJ。
AutoConversion to SMB(Sort-Merge-Bucket) Map Join
基於桶的join,可以轉換成為基於桶的map join。
前提是表按照桶劃分的。排過序的表會比沒有排序的表做map join更快。如果表又是分區表,又是bucket表,可能會慢一點,因為每個mapper需要去擷取一個單鍵分區中的一小塊(eachmapper would need to get a very small chunk of a partition which has a singlekey)。
下面的配置參數使一個SMB轉為map-joinSMB:
sethive.auto.convert.sortmerge.join=true;
sethive.optimize.bucketmapjoin = true;
sethive.optimize.bucketmapjoin.sortedmerge = true;
sethive.auto.convert.sortmerge.join.noconditionaltask=true;
這裡有一個選項去設定大表選擇策略(big table selection policy):
set hive.auto.convert.sortmerge.join.bigtable.selection.policy
= org.apache.hadoop.hive.ql.optimizer.TableSizeBasedBigTableSelectorForAutoSMJ;
預設情況下為平均分區大小,這個大表策略有助於確定選擇stream,相比是hash還是流來說的。
可用的選擇策略列表是:
org.apache.hadoop.hive.ql.optimizer.AvgPartitionSizeBasedBigTableSelectorForAutoSMJ(default)
org.apache.hadoop.hive.ql.optimizer.LeftmostBigTableSelectorForAutoSMJ
org.apache.hadoop.hive.ql.optimizer.TableSizeBasedBigTableSelectorForAutoSMJ
從名字上面就可以判斷用途,特別是用在fact和fact的join中。
GenerateHash Tables on the Task Side
未來的版本,可能會把雜湊放到task side(當前是放在用戶端產生的)。
Prosand Cons of Client-Side Hash Tables (在用戶端產生hash表的優缺點)
無論是產生雜湊,還是多表的雜湊join都有問題。因為用戶端的機器都是用來跑hive用戶端或者用來提交job的。
缺點:
•Data locality: The client machine typically is not a data node. Allthe data accessed is remote and has to be read via the network.
資料分布:用戶端機器一般都不是資料節點,所有的資料訪問都是遠端,必須通過網路讀取。
•Specs: For the same reason, it is not clear what the specificationsof the machine running this processing will be. It might have limitations inmemory, hard drive, or CPU that the task nodes do not have.
空間:出於同樣的原因,這是不清楚的機器有點什麼。任務節點上的記憶體,硬碟,cpu情況不清楚。
•HDFS upload: The data has to be brought back to the clusterand replicated via the distributed cache to be used by task nodes.
HDFS資料上傳:資料返回到叢集和被複製都要通過task節點的分布式緩衝。
好處:
•What is stored in the distributed cache islikely to be smaller than the original table (filter and projection).
因為做了filter或者投影,產生的雜湊表(到分布式緩衝)可能比原始的表要小。
•In contrast, loading hashtables directly onthe task nodes using the distributed cache means larger objects in the cache,potentially reducing opportunities for using MAPJOIN.
相比之下,如果在task端直接使用分布式緩衝載入雜湊表,意味著緩衝會佔用大表佔用,間接的減少使用mapjoin的可能性。
Task-SideGeneration of Hash Tables task端產生雜湊
當在task端產生雜湊時,所有任務節點必須訪問未經處理資料源產生的雜湊表(同時去訪問統一資源)。在正常情況下,這一操作是並行的,不會導致延遲,但是hive有一個概念,就是多任務同時訪問外部的資料來源,如HBase,Database等,這樣就有可能導致延遲了。
FurtherOptions for Optimization 未來的最佳化方向
1.Increasethe replication factor on dimension tables. ----增加維表的複製因子
2.Use the distributedcache to hold dimension tables. ----使用分布式緩衝來存放維表