【轉】Kylin實踐之使用Hive視圖


http://blog.csdn.net/yu616568/article/details/50548967

 

為什么需要使用視圖

       Kylin在使用的過程中使用hive作為cube的輸入,但是有些情況下,hive中的表定義和數據並不能滿足分析的需求,例如有些列的值需要進行處理,有些列的類型不滿足需求,甚至有時候在創建hive表時為了圖方便,hive中的所有列都被定義成了string,因此很多情況下在使用Kylin之前需要對hive上的數據格式進行適當的修剪,但是使用alter table的方式修改hive原始的schema信息未免會對其它依賴hive的組件有所影響(例如可能導致數據導入失敗),於是不得不另辟蹊徑,而此時使用hive的視圖就是一個非常好的方案。

       當然,除了Hive數據源本身schema的限制之外,Kylin對於hive的使用還有一定的限制,這也間接的導致我們需要使用視圖: 
1、同一個項目下使用相同表(可能根據不同的filter條件過濾,或者設置了不同的維度等)創建了不同的cube,會導致查詢的時候定位到錯誤的cube。 
2、只支持星狀模型

如何使用視圖

       Hive目前只支持邏輯視圖,而我們需要的僅僅是對Hive原始的schema信息的修改,而並非希望通過物化視圖優化查詢速度(當然如果有就更好了~),因此目前Hive對視圖的支持可以滿足Kylin的需要。下面根據不同的場景分別介紹一下如何創建視圖作為Kylin的輸入源。

1、分表的情況:兩個表具有相同的結構,但是保存不同的數據,例如一個表保存Android端的訪問數據,一個訪問iOS端的數據,可以通過view搞定。 
例如在我們的環境中有一個用戶有兩張表product_android和product_ios,這兩個表具有相同的表結構,用戶需要將平台(android或者IOS)作為一個維度進行分析,因此我們為其創建了這樣的view: 
create view product_cube as 
select userid, eventid, label, day, ‘android’ as platform from product_android WHERE category=’a’ 
UNION ALL 
select userid, eventid, label, day, ‘ios’ as platform from product_ios WHERE category=’a’; 
這樣可以將product_cube作為事實表創建cube而platform作為其中的一個維度

2、自定義函數,Apache Calcite是支持自定義函數的,但是Kylin支持自定義函數的代價比較大,因此如果需要使用自定義函數,可以在Hive中創建view得到每一個希望的字段。

3、雪花狀模型的支持,目前kylin僅支持星狀模型,而通過創建view可以輕易地把雪花狀模型轉換成星型模型,甚至生成一個大寬表。

4、頻繁修改表字段名,Kylin直接使用hive中的字段名作為元數據,如果頻繁修改事實表或者維度表的字段名會導致元數據錯誤([https://issues.apache.org/jira/browse/KYLIN-1173]),因此通過view增加一層映射是比較好的方法,這樣可以使得原生的hive表的字段名對Kylin的cube透明,此后再需要修改字段名的時候不會對cube有所影響,只需要修改view的定義。

5、UHC維度,當一個維度的cardinality比較大時可能會出現的問題比較多,首先可能導致extract fact columns這一步時導致reducer出現OOM,其次在創建維度字典樹可能會導致維度字典樹太大占據大量的內存,另外會導致cube的構建速度緩慢,占用大量的存儲空間,此時就需要思考一下這樣的UHC維度是否是必須的,是否可以提取出部分信息減小維度,例如timestamp維度,是否可以精確到5分鍾,詳細地址的維度,是否可以精確到縣、鎮,這樣可以大大減小維度數,而且更詳細的信息並沒有太大的統計意義。例如url類型的維度,是否可以把參數去掉只保留訪問路徑。在我們的實踐中,如果用戶有基於細粒度的時間統計的需求,我們會建議將時間規整到5分鍾或者1分鍾,創建view的時候使用如下的方式得到時間列:from_unixtime((unix_timestamp(wanproxy_stat.ts) - unix_timestamp(wanproxy_stat.ts) % 300), ‘yyyy-MM-dd HH:mm:ss’) as ts

6、維度作為度量,在我們創建的cube中有一個例子是這樣的,表中字段有時間、位置、速度,其中時間和位置是維度,速度是度量,類型是double,用戶需要統計根據每一個維度或者維度組合中平均速度小於M並且小於N的平均值,這里就需要根據度量進行過濾,因此還需要將速度作為維度,但是速度的cardinality實在太大,因此我們將速度取整之后將其按5取整,這樣的話,就可以大大降低這一個維度的取值。例如我們的一個用戶有根據速度進行過濾的需求,那么我們為其創建了如下的維度列用於速度的過濾: 
floor(cast(wanproxy_stat.datasize / wanproxy_stat.uploaderusetime as int) / 5) * 5 as velocity 
而原始的速度列cast(wanproxy_stat.datasize / wanproxy_stat.uploaderusetime as int) as speed直接作為度量,那么在查詢的時候可以執行這樣的sql: 
select ts, sum(speed) / count(1) from table where velocity < N and velocity > M group by ts;

7、hive表中類型修改,有時候在創建hive表時為了方便,把所有的表字段都定義成string,但是calcite中對類型的限制比較嚴格,例如extract函數只能對date之類的類型進行操作,所以有時在定義cube之前需要對hive表中的字段進行轉換,創建view就是一個很好的辦法。

8、復合數據類型處理,由於hive中可以定義復雜的數據類型,例如map、struct,而Kylin需要看到的是一個扁平的表結構,所以需要將復雜類型字段進行拆分出維度和度量。

       在我們目前的實踐中,每一個cube依賴的事實表都是通過view創建的,這樣增加了一層映射,可以減小cube對原始表的依賴,提高靈活性,當然在查詢性能上並沒有找到相關的資料說明hive的view性能較差,在我們的實際使用過程中,並沒有發現使用view對Kylin構建cube過程中速度有明顯的影響。

使用視圖的限制

由於hive的限制使用view時需要注意的問題: 
1、由於hive不能對view使用HCatalog獲取數據([https://issues.apache.org/jira/browse/HIVE-10851]),因此當你load一個view的時候Kylin計算表的cardinality的job通常會失敗([https://issues.apache.org/jira/browse/KYLIN-916]),這時就要求用戶知道每一列的cardinality大致的情況,如果實在不確定可以到hive里面查詢一下(可以只查詢一段時間的數據進行估算)。

2、一般情況下,我們創建cube的時候會指定一個分區字段(假設該字段為day),Kylin利用這個字段來增量計算每日的新數據,而對於需要增量計算的cube,在星狀模型中一定有一個表中存在日期字段,一般為事實表,並且這個日期字段是hive表的分區鍵之一,但是對於日志數據在每一行數據中通常還會記錄下該日志的時間(時間戳),一般是timestamp,如果此時需要時間作為維度,假設日期作為其中一個維度,那么就需要創建view將表中時間戳轉換成日期,並將其作為維度,此時view已經存在了一個日期數據,但是建議用戶還是要將分區的時間字段(day字段)放入到定義的view中,並且將其作為cube的分區字段,這樣可以大大加快第一步的執行速度!(掃一個分區和掃整個表)。 
       那么既然有了分區字段表示日期是否只保留Hive的分區字段而不轉換時間戳字段了呢?不可以的,因為分區字段只是標識了一個分區,它的值和時間戳中日值並不一定是相等的關系,雖然通常情況下是相同的,也不能保證某一個分區下的所有時間戳字段的值都是這個日期的(在我們使用的hive表中的確存在這樣的情況)。例如在2016-01-15這個分區中可能前100條數據的時間戳是2014-01-14 23:59:59.xxx,所以你需要在view中保持這兩個字段,一個作為度量(通過表中timestamp字段轉換,參見場景5),一個作為cube的分區字段。

       在我們的使用Kylin的過程中遇到了這些問題可以很好的通過Hive的視圖進行解決,當然還會有一些需求通過視圖能夠很好的實現而不再需要大動干戈的修改hive表或者Kylin的元數據,如果有什么其他的場景還請多多補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM