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 。
星型架構是一種非正規化的結構,多維數據集的每一個維度都直接與事實表相連接,不存在漸變維度,所以數據有一定的冗余,如在地域維度表中,存在國家 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. ----使用分布式緩存來存放維表