1. 教材(只有基本介紹和操作)
Apache Kylin權威指南.pdf
官網公眾微信號(ApacheKylin)
2. 核心概念
度量: 度量是具體考察的聚合數量值,例如:銷售數量、銷售金額、人均購買量。計算機一點描述就是在SQL中就是聚合函數。
例如:select cate,count(1),sum(num) from fact_table where date>’20161112’ group by cate;
count(1)、sum(num)是度量
維度: 維度是觀察數據的角度。例如:銷售日期、銷售地點。計算機一點的描述就是在SQL中就是where、group by里的字段
例如:select cate,count(1),sum(num) from fact_table where date>’20161112’ group by cate;
date、cate是維度
3. 應用與實踐
1.1、kylin公司分享(kylin2.0功能介紹)
http://video.pae.baidu.com/show/videoindex?src=http%3A%2F%2Fm.v.qq.com%2Fpage%2Fu%2Ff%2Fc%2Fu0396tk9hfc.html%3Fptag%3Dbaidu.3g&log_loc=http%3A%2F%2Fv.qq.com%2Fx%2Fpage%2Fu0396tk9hfc.html&loc=http%3A%2F%2Fv.qq.com%2Fx%2Fpage%2Fu0396tk9hfc.html&title=%E6%9D%8E%E6%89%AC-Apache+Kylin+2.0%E6%9C%80%E6%96%B0%E5%8A%9F%E8%83%BD%E5%92%8C%E6%B7%B1%E5%BA%A6%E6%8A%80%E6%9C%AF%E8%A7%A3%E8%AF%BB&query=Apache+kylin%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B&duration=2920&lid=9029643596138362365&srcid=4185&poster=http%3A%2F%2Ft10.baidu.com%2Fit%2Fu%3D3481457922%2C1950467330%26fm%3D171%26s%3DC7C9B3550520F32ADA79C4580300D0F3%26w%3D496%26h%3D280%26img.JPEG&qq-pf-to=pcqq.group
1.2、百度外賣的實踐總結
4. 安裝教程(基於cdh)
http://blog.csdn.net/a920259310/article/details/77771917
5. 深度優化(搜狐內部課程)
1、 kylin job調度::2、Kylin cube構建原理及優化
http://my.tv.sohu.com/pl/9019985/90815107.shtml
2、Kylin cube構建原理及優化::3、kylin cubing算法選擇
http://my.tv.sohu.com/us/259563347/90816849.shtml
4、kylin Hybrid介紹和使用::5、kylin query原理和優化
http://my.tv.sohu.com/us/259563347/90817015.shtml
6. 度量優化
A、 拓展字段(Extended Column)
(1)、實踐證明該優化會導致cube變大,影響查詢性能
(2)、拓展字段限制
11、並且code字段必須來自事實表(fact_tabe),這個是kylin操作上的限制。
12、拓展字段(name)必須和原始字段(code)一對一。否則查詢name字段是空的。
例如:下列查詢acccode和class_name就不是一對一的關系,而是通過m_consume_type的acccode字段關聯,再找到class_code、class_name。就會出現name查詢出來是空的情況。
SELECT b. acccode as acccode,m.class_name as dscrp, SUM(b.opfare) AS sums
FROM
m_rec_consume_copy b
LEFT JOIN m_consume_type m ON b.acccode=m.acccode
WHERE
1=1
GROUP BY b.class_code1,m.class_name
ORDER BY sums DESC
(3)、詳細說明
https://blog.bcmeng.com/post/kylin-dimension.html#extended-column
在OLAP分析場景中,經常存在對某個id進行過濾,但查詢結果要展示為name的情況,比如user_id和user_name。這類問題通常有三種解決方式:
a. 將ID和Name都設置為維度,查詢語句類似select name, count(*) from table where id = 1 group by id,name。這種方式的問題是會導致維度增多,導致預計算結果膨脹;
b. 將id和name都設置為維度,並且將兩者設置為聯合。這種方式的好處是保持維度組合數不會增加,但限制了維度的其它優化,比如ID不能再被設置為強制維度或者層次維度;
c. 將ID設置為維度,Name設置為特殊的Measure,類型為Extended Column。這種方式既能保證過濾id且查詢name的需求,同時也不影響id維度的進一步優化。
所以此類需求我們推薦使用 Extended Column。
7. Kylin - 剪枝優化(維度優化)
怎么確定維度
Where 查詢條件、group by條件都是維度。Sql測試已經證明
Kylin里面設置的維度順序,不影響統計的進行(無論什么順序,只要維度里面有,sql都可以查詢)
剪枝方法
http://baijiahao.baidu.com/s?id=1579212035193751949&wfr=spider&for=pc
http://blog.csdn.net/weixin_36630761/article/details/78086603
http://bigdata.51cto.com/art/201705/538648.htm
http://lxw1234.com/archives/2017/04/849.htm
優缺點:
A、 聯合維度:有效剪枝。跨聯合的查詢會把多個聯合維度查詢出來,再合並。(根據查詢業務分組,就能有效剪枝,並且沒有關聯多個的查詢,從而效率高)
B、 必要維度:join條件、查詢必須帶上的條件,作為必要維度。(多個必要維度時,生成的維度組合可能是不包括必要維度組合本身的。在查詢中出現了按照必要維度查詢不了的情況【這里可能是kylin的一個bug,必要維度組合本身不產生維度,但是sql解析的時候認為產生了所以會匹配成功,然后報錯,並且擋住了其他可能支持這個查詢的cube的匹配】)多個必要維度可以用聯合維度代替。如果維度組(聚合組)的維度包含必要維度所有列,則查詢必要維度就可以進行,因為可以通過必要維度和其他維度組合后的結果來匯總必要維度的查詢結果。
C、 派生維度:把字典表的多個維度字段,不用當作維度構建;而是通過字典表的主鍵來查詢,然后再通過字典表去找到維度。當字典表主鍵和維度字段不是一對一的時候,還需要二次聚合。這個能剪枝,但是影響查詢效率。維度選擇的頁面(Derived維度看到的是外鍵列而不是Derived的列);
D、層級維度:相當於把單個維度的變成了,帶上父級的維度;去掉了一些單獨的層級維度。能剪枝。(必須是查詢對各個層級都有查詢要求,采用層級維度;否則應該使用聯合維度)
E、 維度聚合組:給聚合分組,屬於不同組的不會組合(各組內部才能隨意組合,組和組之間不組合)。
維度順序
其次,ID決定了這個維度在數組中執行查找時該維度對應的第一個維度,例如在上例中time的ID就是1,location對應的ID就是2,product對應的ID為3,這個順序是非常重要的,一般情況我們會將mandatory維度放置在rowkey的最前面,而其它的維度需要將經常出現在過濾條件中的維度放置在靠前的位置,假設在上例的三維數組中,我們經常使用time進行過濾,但是我把time的ID設置為3(location的ID=1,product的ID=2),這時候如果從數組中查找time大於’2016-01-01’並且小於’2016-01-31’,這樣的查詢就需要從這樣的最小的key=<min(location)、min(product)、‘2016-01-01’>掃描到最大的key=<max(location)、max(product)、‘2016-01-31’>,但是如果把time的ID設置為1,掃描的區間就會變成key=<‘2016-01-01’、min(location)、min(product)>到key=<‘2016-01-31’、max(location)、max(product)>,Kylin在實現時需要將Cube的數組存儲在Hbase中,然后按照hbase中的rowkey進行掃描,假設min(location)=’BeiJing’、max(location)=’ZhengZhou’, min(product)=’aaaa’,max(product)=’zzzz’,這樣在第一種情況下hbase中需要掃描的rowkey范圍是[BeiJing-aaaa-2016-01-01, ZhengZhou-zzzz-2016-01-31],而第二種情況需要掃描的rowkey范圍是[2016-01-01-BeiJing-aaaa, 2016-01-31-ZhengZhou-zzzz].可以看出第二種情況可以減少掃面的rowkey,查詢的性能也就更好了。但是在kylin中並不會存儲原始的成員值(例如HangZhou、2016-01-01這樣的值),而是需要對它們進行編碼,是否需要編碼則有后面兩個設置項決定。
8. Rowkey優化
Rowkey設置項說明
1、 Encoding:維度編碼,指定了該維度的值應該使用何種方式進行編碼,選用合適的編碼能夠有效減少維度對空間是使用,在大數據量情況下效果明顯。
2、 維度的編碼(dict、boolean、date、time、integer、fix_length、fix length_hax)。
3、 fix_length則意味着在實際存儲到hbase的rowkey時使用該維度的前Length個字符作為它的值,一般情況下是不建議設置Length的,只有當cardinality比較大時並且只需要取前N個字節就可以表示這個維度時才建議設置Length=N。
4、 Shard By:按維度對數據進行分片,默認Cuboid的數據分片策略是隨機的,並且只能設置一個維度為Share By。
5、 如果Cuboid中的某些行的Shard By Dimension的值是相同的,那么這些行的數據最終將會分配到同一個分片中。
RowKey順序優化
和Hbase 的RowKey優化類似
1.在查詢的過程中,被用作過濾條件的維度可能放在其他維度的前面
2.經常出現的維度應該放在前面
3.基數比較大的維度應該放在前面
維度字典(優缺點)
Dictionary表示需要為這個維度建立字典樹。因為每一個維度的dictionary都會保存在內存中,如果字典樹占用很大的內存會影響kylin的使用甚至導致OOM,對於dictionary的編碼使用的是字典樹,它的原理實際上是為每一個維度成員賦予一個整數的id,實際存儲的時候存儲的是這個id的二進制值(使用int最多占用4個字節),並且保證每一個id的順序和維度成員的順序相同的,例如aaa的id=1,aab的id=2,aac的id=3,這樣在查詢的時候就可以直接根據column>aaa轉換成id>1,方便hbase coprocessor的處理。
9. 精確去重
精確去重(維度統計實現方式)
沒有設置精確去重,但是如果有按照學號統計的維度(並且有count()度量),下面這個sql也是能執行的。這樣就在一些場景下不用使用全局表去實現精確去重
SELECT COUNT(DISTINCT(b.outid))
FROM m_rec_consume_copy b ;
特別說明
如果cube中已經把outid作為一個維度,則不能再將其作為全局字典(kylin上的操作限制)。(按照上一節說的,如果有此維度就已經能count(distinct())獲取精確去重值;不需要全局字典再去重這種低效的方式)。
精確去重(在cube里設置count_distinct的方式)很消耗資源,並且占用空間大,不論是否是全局字典表的方式。
非全局字典精確去重驗證
-- 數據庫驗證的sql
SELECT COUNT(DISTINCT(b.outid))
FROM m_rec_consume_view b ;
SELECT COUNT(DISTINCT(b.outid))
FROM m_rec_consume_view b
where b.opdt >='2017-01-01' AND b.opdt <'2017-02-01';
SELECT COUNT(DISTINCT(b.outid))
FROM m_rec_consume_view b
where b.opdt >='2017-02-01' AND b.opdt <'2017-04-01';
-- kylin驗證的sql::說明沒有全局字典的情況下精確去重的度量在跨分區查詢時是錯誤的
--錯誤: 和sql中的第三個一致
SELECT COUNT(DISTINCT(b.outid))
FROM m_rec_consume_copy b ;
--正確
SELECT COUNT(DISTINCT(b.outid))
FROM m_rec_consume_copy b
where b.opdt >='2017-01-01' AND b.opdt <'2017-02-01';
--正確
SELECT COUNT(DISTINCT(b.outid))
FROM m_rec_consume_copy b
where b.opdt >='2017-02-01' AND b.opdt <'2017-04-01';
----------
驗證結果說明:沒有全局字典的情況下精確去重的度量在跨分區查詢時是錯誤的
其他說明
----------
1.5版本的說明 (需要全局字典表,才能精確去重)
http://lxw1234.com/archives/2016/08/712.htm
2.1版本的說明 (來自kap-manual-zh-cn.pdf文檔,需要驗證)不需要全局字典表,也能精確去重。
實際驗證結果是:不是全局表的情況下去重結果是錯誤的。
全局字典表
1.5.3版本的情況:
非全局字典表最大容量為500萬,(可以通過參數 kylin.dictionary.max.cardinality修改默認值)。
全局字典表最大容量為Integer.MAX_VALUE,即21億多。還是有上限。
全局字典表使用,不使用會影響kylin查詢結果准確性
(如果是分區cube,每個分區會構建自己的字典表在對應的字段上,導致統計的時候字典表編碼或者順序不一致,去重復統計的值就是錯誤的)
全局字典(使用案例)
http://bigdata.51cto.com/art/201705/539360.htm
2.1版本的情況:(來自kap-manual-zh-cn.pdf文檔,需要驗證)
普通字典容量也到21億了,
10. 配置優化
粒度優化
粒度優化對應的是提高Cube的並發度,其設置是在自定義屬性中的
一共有三個屬性可以提高並發度。
1.kylin.hbase.region.cut(共使用幾個分區)
2.kylin.hbase.region.count.min(最少使用幾個分區)
3.kylin.hbase.region.count.max(最多使用幾個分區)
根據相對應的情況調高最少使用分區,降低最大使用分區,能夠有效增加系統的並行度。
Cube Size
最后設置CubeSize,該項的設置會對cuboid轉換成hfile這一步的計算產生影響,並且影響hbase中表的分區大小,可選值為SMALL、MEDIUM和LARGE,在kylin-1.1版本之后可以在配置文件可以設置這三個配置的分區大小,默認情況下SMALL=10GB,MEDIUM=20GB,LARGE=100GB,在計算完全部的cuboid之后會統計所有cuboid文件中key和value的大小,然后根據這個大小和用戶的CubeSize配置決定划分多少region,然后執行一個MR任務計算每一個region的hfile,由於kylin在創建hfile的時候都是通過預分區的方式(通過計算出每一個分區臨界值的key),然后批量load到htable的,所以不會導致region的分裂和合並,所以我們還是建議將CubeSize設置為SMALL,並且配置中將small的配置設置為5GB,這樣可以提高生成hfile這一步的速度(每一個region負責一個region,減小分區的大小會增加reducer的個數)。