天天看點

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

點選檢視第一章 點選檢視第三章

第2章

快 速 入 門

第1章介紹了Apache Kylin的概況,以及它與其他SQL-on-Hadoop技術的不同,相信讀者對Apache Kylin有了一個整體的認識。本章将詳細介紹Apache Kylin的一些核心概念,然後帶領讀者一步步建立Cube,建構Cube,并通過SQL來查詢Cube,使讀者對Apache Kylin有更為直覺的了解。

2.1 核心概念

在使用Apache Kylin之前,需要先了解一下Apache Kylin中的各種概念和術語,為後續章節的學習奠定基礎。

2.1.1 資料倉庫、OLAP與BI

資料倉庫(Data Warehouse)是一種資訊系統的資料儲存理論,此理論強調的是利用某些特殊資料儲存方式,讓所包含的資料特别有利于分析處理,進而産生有價值的資訊并依此做決策。

利用資料倉庫方式存放的資料,具有一旦存入,便不随時間變化而變動的特性,此外,存入的資料必定包含時間屬性,通常,一個資料倉庫會含有大量的曆史性資料,并且它利用特定分析方式,從中發掘出特定的資訊。

OLAP(Online Analytical Process),即聯機分析處理,它可以以多元度的方式分析資料,并且能彈性地提供上卷(Roll-up)、下鑽(Drill-down)和透視分析(Pivot)等操作,是呈現內建性決策資訊的方法,其主要功能在于友善大規模資料分析及統計計算,多用于決策支援系統、商務智能或資料倉庫。與之相差別的是聯機交易處理(OLTP),聯機交易處理側重于基本的、日常的事務處理,包括資料的增、删、改、查。

  • OLAP需要以大量曆史資料為基礎,配合時間點的差異并對多元度及彙整型的資訊進行複雜的分析。
  • OLAP需要使用者有主觀的資訊需求定義,是以系統效率較高。

OLAP的概念,在實際應用中存在廣義和狹義兩種不同的了解。廣義上的了解與字面意思相同,泛指一切不對資料進行更新的分析處理,但更多的情況下OLAP被了解為狹義上的含義,即與多元分析相關,是基于立方體(CUBE)計算而進行的分析。

BI(Business Intelligence),即商務智能,是指用現代資料倉庫技術、線上分析技術、資料挖掘和資料展現技術進行資料分析以實作商業價值。

如今,許多企業已經建立了自己的資料倉庫,用于存放和管理不斷增長的資料,這些資料中蘊含着豐富的商業價值,但隻有使用分析工具對其進行大量篩選、計算和展示後,資料中蘊含的規律、價值和潛在資訊才能被人們所發現與利用。分析人員結合這些資訊進行商業決策和市場活動,進而為使用者提供更好的服務,為企業創造更大的價值。

2.1.2 次元模組化

次元模組化用于決策制定,并側重于業務如何表示和了解資料。基本的次元模型由次元和度量兩類對象組成。次元模組化嘗試以邏輯、可了解的方式呈現資料,以使得資料的通路更加直覺。次元設計的重點是簡化資料和加快查詢。

次元模型是資料倉庫的核心。它經過精心設計和優化,可以為資料分析和商業智能(BI),檢索并彙總大量的相關資料。在資料倉庫中,資料修改僅定期發生,并且是一次性開銷,而讀取是經常發生的。對于一個資料檢索效率比資料處理效率重要得多的資料結構而言,非标準化的次元模型是一個不錯的解決方案。

在資料挖掘中有幾種常見的多元資料模型,如星形模型(Star Schema)、雪花模型(Snowflake Schema)、事實星座模型(Fact Constellation)等。

星形模型中有一個事實表,以及零個或多個次元表,事實表與次元表通過主鍵外鍵相關聯,次元表之間沒有關聯,就像很多星星圍繞在一個恒星周圍,故名為星形模型。

如果将星形模型中的某些次元表再做規範,抽取成更細的次元表,讓次元表之間也進行關聯,那麼這種模型稱為雪花模型。

事實星座模型是更為複雜的模型,其中包含多個事實表,而次元表是公用的,可以共享。

2.1.3 事實表和次元表

事實表(Fact Table)是指存儲事實記錄的表,如系統日志、銷售記錄等,并且是次元模型中的主表,代表着鍵和度量的集合。事實表的記錄會不斷地動态增長,是以它的體積通常遠大于其他表,通常事實表占據資料倉庫中90%或更多的空間。

次元表(Dimension Table),也稱維表或查找表(Lookup Table),是與事實表相對應的一種表。次元表的目的是将業務含義和上下文添加到資料倉庫中的事實表和度量中。次元表是事實表的入口點,次元表實作了資料倉庫的業務接口。它們基本上是事實表中的鍵引用的查找表。它儲存了次元的屬性值,可以與事實表做關聯,相當于将事實表上經常出現的屬性抽取、規範出來用一張表進行管理,常見的次元表有:日期表(存儲日期對應的 周、月、季度等屬性)、地點表(包含國家、省/州、城市等屬性)等。使用次元表的好處如下:

  • 減小了事實表的大小;
  • 便于次元的管理和維護,增加、删除和修改次元的屬性時,不必對事實表的大量記錄進行改動;
  • 次元表可以為多個事實表同時使用,減少重複工作。

2.1.4 次元和度量

次元和度量是資料分析中的兩個基本概念。

次元是人們觀察資料的特定角度,是考慮問題時的一類屬性。它通常是資料記錄的一個特征,如時間、地點等。同時,次元具有層級概念,可能存在細節程度不同的描述方面,如日期、月份、季度、年等。

在資料倉庫中,可以在數學上求和的事實屬性稱為度量。例如,可以對度量進行總計、平均、以百分比形式使用等。度量是次元模型的核心。通常,在單個查詢中檢索數千個或數百萬個事實行,其中對結果集執行數學方程。

在一個SQL查詢中,Group By的屬性通常就是次元,而其所計算的值則是度量,如在下面這個查詢中,part_dt和lstg_site_id是次元,sum(price)和count(distinct seller_id)是度量。

select part_dt, lstg_site_id, sum(price) as total_selled, count(distinct seller_id)
as sellers from kylin_sales group by part_dt, lstg_site_id           

2.1.5 Cube、Cuboid和Cube Segment

Cube(或稱Data Cube),即資料立方體,是一種常用于資料分析與索引的技術,它可以對原始資料建立多元度索引,大大加快資料的查詢效率。

Cuboid特指Apache Kylin中在某一種次元組合下所計算的資料。

Cube Segment指針對源資料中的某一片段計算出來的Cube資料。通常,資料倉庫中的資料數量會随時間的增長而增長,而Cube Segment也是按時間順序建構的。

2.2 在Hive中準備資料

上一節介紹了Apache Kylin中的常見概念。在本節中将介紹準備Hive資料時的一些注意事項。需要進行分析的資料必須先儲存為Hive表的形式,隻有這樣Apache Kylin才能從Hive中導入資料、建立Cube。

Apache Hive是一個基于Hadoop的資料倉庫工具,最初由Facebook開發并貢獻到Apache軟體基金會。Hive可以将結構化的資料檔案映射為資料庫表,并可以将SQL語句轉換為MapReduce或Tez任務運作,進而讓使用者以類SQL(HiveQL,HQL)的方式管理和查詢Hadoop上的海量資料。

此外,Hive提供了多種方式(如指令行、API和Web服務等)供第三方友善地擷取和使用中繼資料并進行查詢。今天,Hive已經成為Hadoop資料倉庫的首選,是Hadoop不可或缺的一個重要元件,很多項目都相容或內建Hive。鑒于此,Apache Kylin選擇Hive作為原始資料的主要來源。

在Hive中準備待分析的資料是使用Apache Kylin的前提。将資料導入Hive表的方法很多,使用者管理資料的技術和工具也多種多樣,故其具體步驟不在本書的讨論範圍之内,如有需要可以參閱Hive的文檔。這裡着重闡述幾個需要注意的事項。

2.2.1 多元資料模型

目前Apache Kylin既支援星形資料模型,也支援雪花資料模型,這是基于以下考慮:

星形模型與雪花模型是最為常用的資料模型;

由于隻有一個大表,相比于其他模型更适合大資料處理;

其他模型可以通過一定的轉換,變為星形模型或雪花模型。

2.2.2 次元表的設計

除了資料模型以外,Apache Kylin還對次元表有一定的要求,如:

1)要具有資料一緻性。主鍵值必須唯一,Apache Kylin會進行檢查,如果有兩行資料的主鍵相同,則系統就會報錯。

2)次元表越小越好。Apache Kylin支援選擇是否将次元表加載到記憶體中以供查詢,過大的表不适合作為次元表,預設的門檻值是300Mb。

3)改變頻率低。Apache Kylin會在每次建構中試圖重用次元表快照,如果次元表經常改變的話,重用就會失效,這會導緻要經常對次元表建立快照。

4)次元表最好不是Hive視圖(View),雖然在Apache Kylin v1.5.3中加入了對次元表是視圖的支援,但每次都需要将視圖物化,導緻額外的時間成本。

2.2.3 Hive表分區

Hive表支援多分區(partition)。簡單來說,一個分區就是一個檔案目錄,存儲了特定的資料檔案。當有新的資料生成的時候,可以将資料加載到指定的分區,讀取資料的時候也可以指定分區。對于SQL查詢,如果查詢中指定了分區列的屬性條件,則Hive會智能地選擇特定分區(目錄),進而避免全量資料的掃描,減少讀寫操作對叢集的壓力。

下面的一組SQL語句,示範了如何使用分區:

Hive> create table invites (id int, name string) partitioned by (ds string) row format
delimited fields terminated by 't' stored as textfile;?
Hive> load data local inpath '/user/hadoop/data.txt' overwrite into table invites
partition (ds='2016-08-16');?

Hive> select * from invites where ds ='2016-08-16';           

Apache Kylin支援增量的Cube建構,通常是按時間屬性來增量地從Hive表中抽取資料。如果Hive表正好是按此時間屬性做分區的話,那麼可以利用到Hive分區的好處,每次Hive建構的時候可以直接跳過不相幹日期的資料,節省Cube建構的時間。這樣的列在Apache Kylin裡也稱為分割時間列(partition time column),通常它應該也是Hive表的分區列。

2.2.4 了解次元的基數

次元的基數(Cardinality)指的是該次元在資料集中出現的不同值的個數。例如,“國家”是一個次元,有200個不同的值,那麼此次元的基數是200。通常,一個次元的基數為幾十到幾萬,個别次元如“使用者ID”的基數會超過百萬甚至千萬,基數超過一百萬的次元通常被稱為超高基數次元(Ultra High Cardinality,UHC),需要引起設計者的注意。

Cube中所有次元的基數可以展現Cube的複雜度,如果一個Cube中有多個超高基數次元,那麼這個Cube膨脹的幾率就會很高。在建立Cube前對所有次元的基數做一個了解,可以幫助設計合理的Cube。計算基數有多種途徑,最簡單的方法就是讓Hive執行一個count distinct的SQL查詢,同時Apache Kylin也提供了計算基數的方法,這部分内容會在2.4.1節中進行介紹。

2.2.5 樣例資料

如果需要一些簡單資料來快速體驗Apache Kylin,也可以使用Apache Kylin自帶的樣例資料。運作“${KYLIN_HOME}/bin/sample.sh”來導入樣例資料,然後就能繼續按下面的流程建立模型和Cube。下面的示例和配圖都是基于樣例資料制作的。

2.3 安裝和啟動Apache Kylin

如果資料已經在Hive中準備好,并已經滿足2.2節介紹的條件,那麼就可以開始安裝和使用Apache Kylin了。本節将介紹Apache Kylin的安裝環境及啟動方法。

2.3.1 環境準備

衆所周知,Apache Kylin依賴于Hadoop叢集處理大量資料集。是以在安裝Apache Kylin之前必須準備Hadoop環境。由于Apach Hadoop版本管理混亂,推薦安裝Cloudera CDH或Hortonworks HDP等商業Hadoop發行版。

2.3.2 必要元件

準備好Hadoop環境之後,還需要安裝一些應用以支援Apache Kylin的分析查詢,其中必不可少的有YARN、HDFS、MapReduce、Hive、HBase、Zookeeper和其他一系列服務以保證Apache Kylin的運作穩定可靠。

2.3.3 啟動Apache Kylin

一切準備就緒之後,就能夠啟動Apache Kylin了。首先從Apache Kylin下載下傳一個适用Hadoop版本的二進制檔案,解壓相應的二進制檔案,并配置環境變量KYLIN_HOME指向Kylin檔案夾。之後運作“$KYLIN_HOME/bin/kylin.sh start”腳本啟動Apache Kylin。

Apache Kylin 啟動後,可以通過浏覽器“

http://:7070/kylin

”進行通路。其中,“”為具體的機器名、IP 位址或域名,預設端口為“7070”,初始使用者名和密碼為“ADMIN/KYLIN”。伺服器啟動後,您可以通過檢視“$KYLIN_HOME/logs/kylin.log”獲得運作日志。

2.4 設計Cube

如果資料已經在Hive中準備好,并已經滿足2.3節介紹的條件,那麼就可以開始設計和建立Cube了,本節将按正常的步驟介紹Cube是如何建立的。

2.4.1 導入Hive表定義

登入Apache Kylin的Web界面,建立新的或選擇一個已有項目後,需要做的就是将Hive表的定義導入Apache Kylin。

點選 Web界面的“Model”→“Data source”下的“Load Hive Table Metadata”圖示,然後輸入表的名稱(可以一次導入多張表,以逗号分隔表名)(如圖2-1所示),點選按鈕“Sync”,Apache Kylin就會使用Hive的API從Hive中擷取表的屬性資訊。

導入成功後,表的結構資訊會以樹狀形式顯示在頁面的左側,可以點選展開或收縮,如圖2-2所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

同時,Apache Kylin會在背景觸發一個MapReduce任務,計算此表每個列的基數。通常稍過幾分鐘後重新整理頁面,就會看到基數資訊顯示出來,如圖2-3所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

需要注意的是,這裡Apache Kylin對基數的計算采用的是HyperLogLog的近似算法,與精确值略有誤差,但作為參考值已經足夠。

2.4.2 建立資料模型

有了表資訊後,就可以開始建立資料模型了。資料模型(Data Model)是Cube的基礎,主要根據分析需求進行設計。有了資料模型以後,定義Cube的時候就可以直接從此模型定義的表和列中進行選擇了,省去了重複指定連接配接(JOIN)條件的步驟。基于一個資料模型可以建立多個Cube,友善減少使用者的重複性工作。

在Apache Kylin界面的“Model”頁面,點選“New”→“New Model”指令,開始建立資料模型。給模型輸入名稱後,選擇一個事實表(必需的),然後添加次元表(可選),如圖2-4所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

添加次元表的時候,首先選擇表之間的連接配接關系,同時選擇表之間的連接配接類型:是inner jion還是left jion,并為建立的次元表輸入别名。同時可以選擇是否将其以快照(Snapshot)形式存儲到記憶體中以供查詢。當次元表小于300MB時,推薦啟用次元表以快照形式存儲,以簡化Cube計算和提高系統整體效率。當次元表超過300MB上限時,則建議關閉次元表快照,以提升Cube建構的穩定性與查詢的性能。然後選擇連接配接的主鍵和外鍵,這裡也支援多主鍵,如圖2-5所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

接下來選擇用作次元和度量的列。這裡隻是選擇一個範圍,不代表這些列将來一定要用作 Cube的次元或度量,你可以把所有可能會用到的列都選進來,後續建立Cube的時候,将隻能從這些列中進行選擇。

選擇次元列時,次元可以來自事實表或次元表,如圖2-6所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

選擇度量列時,度量隻能來自事實表或不加載進記憶體的次元表,如圖2-7所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

最後一步,是為模型補充分割時間列資訊和過濾條件。如果此模型中的事實表記錄是按時間增長的,那麼可以指定一個日期/時間列作為模型的分割時間列,進而可以讓Cube按此列做增量建構,關于增量建構的具體内容參見第4章。

過濾(Filter)條件是指,如果想把一些記錄忽略掉,那麼這裡可以設定一個過濾條件。Apache Kylin在向Hive請求源資料的時候,會帶上此過濾條件。如圖2-8所示,會隻保留金額(price)大于0的記錄。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

最後,點選“Save”儲存此資料模型,随後它将出現在“Model”的清單中。

2.4.3 建立Cube

本節簡單介紹了建立Cube時的各種配置選項,但是由于篇幅限制,這裡沒有對Cube的配置和優化進行進一步展開介紹。讀者可以在後續的章節(如第3章“Cube優化”)中找到關于Cube的配置和優化的更詳細的介紹。接下來開始Cube的建立。點選“New”→“New Cube”指令會開啟一個包含若幹步驟的向導。

第一步,選擇要使用的資料模型,并為此Cube輸入一個唯一的名稱(必需的)和描述(可選)(如圖2-9所示);這裡還可以輸入一個郵件通知清單,以在建構完成或出錯時收到通知。如果不想接收在某些狀态的通知,可以從“Notification Events”中将其去掉。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

第二步,添加Cube的次元。點選“Add Dimension”按鈕添加次元,Apache Kylin會用一個樹狀結構呈現出所有列,使用者隻需勾選想要的列即可,同時需要為每個次元輸入名字,可以設定是普通次元或是衍生(Derived)次元(如圖2-10所示)。如果被設定為衍生次元的話,由于這些列值都可以從該次元表的主鍵值中衍生出來,是以實際上隻有主鍵列會被Cube加入計算。而在Apache Kylin的具體實作中,往往采用事實表上的外鍵替代主鍵進行計算和存儲。但是邏輯上可以認為衍生列來自次元表的主鍵。

第三步,建立度量。Apache Kylin支援的度量有SUM、MIN、MAX、COUNT、COUNT_DISTINCT、TOP_N、EXTENDED_COLUMN、PERCENTILE等。預設Apache Kylin會建立一個Count(1)度量。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

可以通過點選“Bulk Add Measure”按鈕批量添加度量。目前對于批量添加度量,Apache Kylin隻支援SUM、MIN、MAX等簡單函數。隻需要選擇度量類型,然後再選擇需要計算的列,如圖2-11所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

如果需要添加複雜度量,可以點選“+Measure”按鈕來添加新的度量。請選擇需要的度量類型,然後再選擇适當的參數(通常為列名)。圖2-12所示為一個SUM(price)的示例。

重複以上操作,建立所需要的度量。Apache Kylin可以支援在一個Cube中有上百個的度量,添加完所有度量後,點選“Next”按鈕,如圖2-13所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門
帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

第四步,進行關于Cube資料重新整理的設定(如圖2-14所示)。在這裡可以設定自動合并的門檻值、自動合并觸發時保留的門檻值、資料保留的最小時間,以及第一個Segment的起點時間(如果Cube有分割時間列),詳細内容請參考第4章。

第五步,進階設定。在此頁面可以設定次元聚合組和Rowkey屬性。

預設Apache Kylin會把所有次元放在同一個聚合組(Aggregation Group,也稱次元組)中,如果次元數較多(如>15),建議使用者根據查詢的習慣和模式,點選“New Aggregation Group+”指令,将次元分布到多個聚合組中。通過使用多個聚合組,可以大大降低Cube中的Cuboid數量。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

舉例說明,一個Cube有(M+N)個次元,如果把這些次元都放置在一個組裡,那麼預設會有2(M+N)個Cuboid;如果把這些次元分為兩個不相交的聚合組,第一個組有M個次元,第二個組有N個次元,那麼Cuboid的總數量将被減至2M + 2N,比之前的2(M+N)極大地減少了。

在單個聚合組中,可以對次元設定一些進階屬性,如Mandatory Dimensions、Hierarchy Dimensions、Joint Dimensions等。這幾種屬性都是為優化Cube的計算而設計的,了解這些屬性的含義對于更好地使用Cube至關重要。

強制次元(Mandatory Dimensions):指的是那些總是會出現在Where條件或 Group By語句裡的次元。通過指定某個次元為強制次元,Apache Kylin可以不預計算那些不包含此次元的Cuboid,進而減少計算量。

層級次元(Hierarchy Dimensions):是指一組有層級關系的次元,如“國家”“省”“市”,這裡“國家”是進階别的次元,“省”“市”依次是低級别的次元。使用者會按進階别次元進行查詢,也會按低級别次元進行查詢,但當查詢低級别次元時,往往會帶上進階别次元的條件,而不會孤立地審視低次元的資料。例如,使用者會點選“國家”作為次元來查詢彙總資料,也可能點選“國家”+“省”,或者“國家”+“省”+“市”來進行查詢,但是不會跨越“國家”直接點選“省”或“市”來進行查詢。通過指定層級次元,Apache Kylin可以略過不滿足此模式的Cuboid。

聯合次元(Joint Dimensions):是将多個次元視作一個次元,在進行組合計算的時候,它們要麼一起出現,要麼均不出現,通常适用于以下幾種情形:

  • 總是一起查詢的次元;
  • 彼此之間有一定映射關系,如 USER_ID 和 EMAIL;
  • 基數很低的次元,如性别、布爾類型的屬性。

如圖2-15所示,先通過在“Includes”中選擇要添加的次元到本聚合組中,然後根據模型特征和查詢模式,設定進階次元屬性。“Hierarchy Dimensions”和“Joint Dimensions”可以設定多組,但要注意,一個次元出現在某個屬性中後,将不能再設定另一種屬性。但是一個次元,可以出現在多個聚合組中。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

在Apache Kylin中是以Key-Value的形式将Cube的建構結果存儲到Apache HBase中的。我們知道,HBase 是一種單索引、支援超寬表的資料存儲引擎。HBase的Rowkey,即行鍵是用來檢索其他列的唯一索引。Apache Kylin需要按照多個次元來對度量進行檢索,是以在存儲到HBase的時候,需要将多個次元值進行拼接組成Rowkey。圖2-16中介紹了Apache Kylin将Cube存儲在 HBase中的原理。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

由于同一次元中的數值長短不一,如國家名,短的如“中國”,長的如“巴巴新幾內亞”,是以将多個不同列的值進行拼接的時候,要麼添加分隔符,要麼通過某種編碼使各個列所占的寬度固定。Apache Kylin為了能夠在HBase上高效地進行存儲和檢索,會使用第二種方式對次元值進行編碼。次元編碼的優勢如下:

  • 壓縮資訊存儲空間;
  • 提高掃描效率,減少解析開銷。

編碼(Encoding)代表了該次元的值使用何種方式進行編碼,預設采用字典(Dictionary)編碼技術。而合适的編碼能夠減少次元對空間的占用。例如,我們可以把所有的日期用三個位元組進行編碼,相比于使用字元串,或者使用長整數形式進行存儲,我們的編碼方式能夠大大減少每行Cube資料的體積。而Cube中可能存在數以億計的行,累加起來使用編碼節約的空間将是非常龐大的。

目前Apache Kylin支援的編碼方式有以下幾種。

  • Dictionary編碼:字典編碼是将所有此次元下的值建構成一張映射表,進而大大節約存儲空間。另外,字典是保持順序的,這樣可以使得在HBase中進行比較查詢的時候,依然使用編碼後的值,而無須解碼。Dictionary的優勢是,産生的編碼非常緊湊,尤其在次元的值基數小且長度大的情況下,Dictionary編碼特别節約空間。由于産生的字典在使用時加載進建構引擎和查詢引擎,是以在次元的基數大、長度也大的情況下,容易造成建構引擎或者查詢引擎的記憶體溢出。在Apache Kylin中,字典編碼允許的基數上限預設是500萬(由其參數“kylin.dictionary.max.cardinality”配置)。
  • Date編碼:将日期類型的資料使用三個位元組進行編碼,支援從0000-01-01到9999-01-01中的每一個日期。
  • Time編碼:僅支援表示從1970-01-01 00:00:00到 2038-01-19 03:14:07的時間,且Timestamp類型的次元經過編碼和反編碼之後,會失去毫秒資訊,是以說Time編碼僅僅支援到秒。但是Time編碼的優勢是每個次元僅使用四個位元組,相比普通的長整數編碼節約了一半空間。如果能夠接受秒級的時間精度,可以選擇Time來編碼代表時間的次元。
  • Integer編碼:Integer編碼适合于對int或bigint類型的值進行編碼,它無須額外存儲,同時可以支援很大的基數。使用時需要提供一個額外的參數“Length”來代表需要多少個位元組。“Length”的長度為1~8。如果用來編碼int32類型的整數,可以将“Length”設為“4”;如果用來編int64類型的整數,可以将“Length”設為“8”。在多數情況下,如果我們知道一個整數類型次元的可能值都很小,那麼就能使用“Length”為“2”甚至是“1”的int編碼來存儲,這能夠有效避免存儲空間的浪費。
  • Fixed_length編碼:該編碼需要提供一個額外的參數“Length”來代表需要多少個位元組。對于基數大、長度也大的次元來說,使用Dict可能不能正常執行,于是可以采用一段固定長度的位元組來存儲代表次元值的位元組數組,該數組為字元串形式的次元值的UTF-8位元組。如果次元值的長度大于預設的Length,那麼超出的部分将會被截斷。此編碼方式其實隻是将原始值截斷或補齊成相同長度的一組位元組,沒有額外的轉換,是以空間效率較差,通常隻是一種權宜手段。

在未來,Apache Kylin還有可能為特定場景、特定類型的次元量身定制特别的編碼方式,如在很多行業,身份證号碼可能是一個重要的次元。但是身份證号碼由于其特殊性而不能使用整數類型的編碼(身份證号碼的最後一位可能是X),其高基數的特點也決定了其不能使用Dict編碼,在目前的版本中隻能使用Fixed_length編碼,但顯然Fixed_length不能充分利用身份證号碼中大部分位元組是數字的特性來進行深度編碼,是以存在一定程度的存儲空間的浪費。

同時,各個次元在Rowkey中的順序,也會對查詢的性能産生較明顯的影響。在這裡使用者可以根據查詢的模式和習慣,通過拖曳的方式調整各個次元在Rowkey上的順序(如圖2-17所示)。一般原則是,将過濾頻率高的列放置在過濾頻率低的列之前,将基數高的列放置在基數低的列之前。這樣做的好處是,充分利用過濾條件來縮小在HBase中掃描的範圍,進而提高查詢的效率。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

在建構Cube時,可以通過次元組合白名單(Mandatory Cuboids)確定想要建構的Cuboid能被成功建構(如圖2-18所示)。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

Apache Kylin支援對于複雜的COUNT DISTINCT度量進行字典建構,以保證查詢性能。目前提供兩種字典格式,即Global Dictionary和Segment Dictionary(如圖2-19所示)。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

其中,Global Dictionary可以将一個非integer的值轉成integer值,以便bitmap進行去重,如果你要計算COUNT DISTINCT的列本身已經是integer類型,那就不需要定義Global Dictionary。并且Global Dictionary會被所有segment共享,是以支援跨segments做上卷去重操作。

而Segment Dictionary雖然也是用于精确計算 COUNT DISTINCT的字典,但與Global Dictionary不同的是,它是基于一個segment的值建構的,是以不支援跨segments的彙總計算。如果你的cube不是分區的或者能保證你的所有SQL按照partition column進行group by, 那麼最好使用Segment Dictionary而不是Global Dictionary,這樣可以避免單個字典過大的問題。

Apache Kylin目前提供的Cube建構引擎有兩種:MapReduce和Spark(如圖2-20所示)。如果你的 Cube隻有簡單度量(如SUM、 MIN、MAX),建議使用Spark。如果Cube中有複雜類型度量(如COUNT DISTINCT、 TOP_N),建議使用MapReduce。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

為了提升建構性能,你可以在Advanced Snapshot Table中将維表設定為全局維表,同時提供不同的存儲類型(如圖2-21所示)。

在建構時 Apache Kylin允許在Advanced Column Family中對度量進行分組(如圖2-22所示)。如果有超過一個的 COUNT DISTINCT 或 Top_N 度量, 你可以将它們放在更多列簇中,以優化與HBase 的I/O。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門
帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

第五步,為Cube配置參數。和其他Hadoop工具一樣,Apache Kylin使用了很多配置參數,使用者可以根據具體的環境、場景等配置不同的參數進行靈活調優。Apache Kylin全局的參數值可以在conf/kylin.properties檔案中進行配置;如果Cube需要覆寫全局設定的話,需在此頁面指定。點選“+Property”按鈕,然後輸入參數名和參數值,如圖2-23所示,指定“kylin.hbase.region.cut”的值為“1”,這樣,此Cube在存儲的時候,Apache Kylin将會按每個HTable Region存儲空間為1GB來建立HTable Region。如果使用者希望任務從YARN中擷取更多記憶體,可以設定kylin.engine.mr.config-override.mapreduce.map.memory.mb、kylin.engine.mr.config-override.mapreduce.map.java.opts 等mapreduce相關參數。如果使用者希望Cube的建構任務使用不同的YARN 資源隊列,可以設定kylin.engine.mr.config-override.mapreduce.job.queuename。這些配置均可以在Cube級别重寫。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

然後點選“Next”按鈕到最後一個确認頁面,如有修改,點“Prev”按鈕傳回進行修改,最後點“Save”按鈕進行儲存,一個Cube就建立完成了。建立好的Cube會顯示在“Cubes”清單中,如要對Cube的定義進行修改,隻需點“Edit”按鈕就可以修改。也可以展開此Cube行以檢視更多資訊,如JSON格式的中繼資料、通路權限、通知清單等。

2.5 建構Cube

本節簡單地介紹了建構Cube的相關操作說明和設定,受篇幅的限制許多具體内容沒有深入展開,讀者可以從第3章“Cube優化”和第4章“增量建構”中獲得更詳細的介紹。

新建立的Cube隻有定義,而沒有計算的資料,它的狀态是“DISABLED”,是不會被查詢引擎挑中的。要想讓Cube有資料,還需對它進行建構。Cube的建構方式通常有兩種:全量建構和增量建構,兩者的建構步驟是完全一樣的,差別隻在于建構時讀取的資料源是全集還是子集。

Cube的建構包含以下步驟,由任務引擎排程執行:

1)建立臨時的Hive平表(從Hive中讀取資料);

2)計算各次元的不同值,并收集各Cuboid的統計資料;

3)建立并儲存字典;

4)儲存Cuboid統計資訊;

5)建立HTable;

6)計算Cube (一輪或若幹輪計算);

7)将Cube計算結果轉成HFile;

8)加載HFile到HBase;

9)更新Cube中繼資料;

10)垃圾回收。

上述步驟中,前五步是為計算Cube而做的準備工作,如周遊次元值來建立字典,對資料做統計和估算以建立HTable等。第六步是真正的Cube計算,取決于使用的Cube算法,它可能是一輪MapReduce任務,也可能是N(在沒有優化的情況下,N可以被視作次元數)輪疊代的MapReduce。

由于Cube運算的中間結果是以SequenceFile的格式存儲在HDFS上的,是以為了導入HBase,還需要進行第七步操作,将這些結果轉換成HFile(HBase檔案存儲格式)。第八步通過使用HBase BulkLoad工具,将HFile導入HBase叢集,這一步完成後,HTable就可以查詢到資料。第九步更新Cube的資料,将此次建構的Segment的狀态從“NEW”更新為“READY”,表示已經可供查詢。最後一步,清理建構過程中生成的臨時檔案等垃圾,釋放叢集資源。

Monitor頁面會顯示目前項目下近期的建構任務。圖2-24中顯示了一個正在運作的Cube建構任務,目前進度46.67%。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

點選任務右邊的“>”按鈕,可以将其展開得到該任務每一步的詳細資訊,如圖2-25所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

如果Cube建構任務中的某一步驟是執行Hadoop任務的話,會顯示Hadoop任務的連結,點選即可跳轉到Hadoop對應的任務監測頁面,如圖2-26所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

如果任務執行中的某一步驟報錯,任務引擎會将任務狀态置為“ERROR”并停止後續操作的執行,等待使用者排錯。在錯誤排除後,使用者可以點選“Resume”從上次報錯的位置恢複執行。或者如果需要修改Cube或重新開始建構,使用者需點選“Discard”來放棄此次建構。

接下來介紹幾種不同的建構方式。

2.5.1 全量建構和增量建構

1. 全量建構

對資料模型中沒有指定分割時間列資訊的Cube,Apache Kylin會采用全量建構,即每次都從Hive中讀取全部的資料來開始建構。通常它适用于以下兩種情形:

  • 事實表的資料不是按時間增長的;
  • 事實表的資料比較小或更新頻率很低,全量建構不會造成太大的存儲空間浪費。

    2. 增量建構

進行增量建構的時候,Apache Kylin每次都會從Hive中讀取一個時間範圍内的資料,然後對其進行計算,并以一個Segment的形式儲存。下次建構的時候,自動以上次結束的時間為起點時間,再選擇新的終止時間進行建構。經過多次建構後,Cube中會有多個Segment依次按時間順序進行排列,如 Seg-1, Seg-2,…,Seg-N。進行查詢的時候,Apache Kylin會查詢一個或多個Segment然後再做聚合計算,以便傳回正确的結果給請求者。

使用增量建構的優勢是,每次隻需要對新增資料進行計算,避免了對曆史資料進行重複計算。對于資料量很大的Cube,使用增量建構是非常有必要的。

圖2-27所示為建構一個Segment的Cube的輸入框,需要使用者選擇時間範圍。

在從Hive中讀取源資料的時候,Apache Kylin會帶上此時間條件,如圖2-28所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門
帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

增量建構抽取資料的範圍,采用前包後閉原則,也即包含開始時間,但不包含結束時間,進而保證上一個Segment的結束時間與下一個Segment的起始時間相同,但資料不會重複。

如果使用Apache Kylin的Web GUI觸發,起始時間會被自動填寫,使用者隻需選擇結束時間。如果使用Rest API觸發,使用者則需確定時間範圍不會與已有的Segment重合。

2.5.2 曆史資料重新整理

Cube建構完成以後,如果某些曆史資料發生了變動,需要針對相應的Segment重新進行計算,這種建構稱為重新整理。重新整理通常隻針對增量建構的Cube而言,因為全量建構的Cube隻要重新全部建構就可以得到更新;而增量更新的Cube因為有多個Segment,需要先選擇要重新整理的Segment,然後再進行重新整理。

圖2-29所示為送出重新整理的請求頁面,使用者需要在下拉清單中選擇一個時間區間。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

送出重新整理請求以後,生成的建構任務與最初的建構任務完全相同。

在重新整理的同時,Cube仍然可以被查詢,隻是傳回的是陳舊資料。當Segment重新整理完畢後,新Segment會立即生效,查詢開始傳回最新的資料。原Segment則成為垃圾,等待回收。

2.5.3 合并

随着時間的遷移,Cube中可能存在較多數量的Segment,使得查詢性能下降,并且會給HBase叢集管理帶來壓力。對此,需要适時地做Segment的合并,将若幹個小Segment合并成較大的Segment。

合并有如下優勢:

  • 合并相同的Key,進而減少Cube的存儲空間;
  • 由于Segment減少,可以減少查詢時的二次聚合,提高了查詢性能;
  • HTable數量得以減少,便于叢集的管理。

下面來看看合并的操作步驟,圖2-30中的Cube有兩個Segment。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

現在觸發一個合并,點選“Actions” →“Merge”;選擇要合并的起始Segment和結束Segment,生成一個合并的任務,如圖2-31所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

進行合并的時候,Apache Kylin會直接以最初各個Segment建構時生成的Cuboid檔案作為輸入内容,不需要從Hive中加載原始資料。後續的步驟跟建構時基本一緻。直到新的HTable加載完成,Apache Kylin才會解除安裝原來的HTable,以確定在整個合并過程中,Cube都是可以查詢的。

合并完成後,此Cube的Segment減少為1個,如圖2-32所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

2.6 查詢Cube

本節簡要介紹如何查詢Cube。更多内容請參考後續章節(如第5章“查詢與可視化”)。

Cube建構好以後,狀态變為“READY”,就可以進行查詢了。Apache Kylin的查詢語言是标準SQL的SELECT語句,這是為了獲得與大多數BI系統和工具無縫內建的可能性。一般的查詢語句類似以下SQL語句:

SELECT DIM1, DIM2, …, MEASURE1, MEASURE2… FROM FACT_TABLE 
     INNER JOIN LOOKUP_1 ON FACT_TABLE.FK1 = LOOKUP_1.PK 
     INNER JOIN LOOKUP_2 ON FACT_TABLE.FK2 = LOOKUP_2.PK
WHERE FACT_TABLE.DIMN = ‘’ AND …
      GROUP BY DIM1, DIM2…
           

需要了解的是,隻有當查詢的模式跟Cube定義相比對的時候,Apache Kylin才能夠使用Cube的資料來完成查詢。“Group By”的列和“Where”條件裡的列,必須是在次元中定義的列,而SQL中的度量,應該跟Cube中定義的度量一緻。

在一個項目下,如果有多個基于同一模型的Cube,而且它們都滿足查詢對表、次元和度量的要求,Apache Kylin會挑選一個“最優的”Cube來進行查詢。這是一種基于成本(cost)的選擇,Cube的成本計算涉及多方面因素,如Cube的次元數、度量、資料模型的複雜度等。

如果查詢是在Apache Kylin的Web GUI上進行的,查詢結果會以表的形式展現,如圖2-33所示。所執行的Cube名稱也會一同顯示。使用者可以點選“Visualization”按鈕生成簡單的可視化圖形,或點選“Export”按鈕下載下傳結果集到本地。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

2.6.1 Apache Kylin查詢介紹

Apache Kylin使用Apache Calcite做SQL文法分析,并且Apache Kylin深度定制了Calcite。Apache Calcite是一個開源的SQL引擎,它提供了标準SQL語言解析、多種查詢優化和連接配接各種資料源的能力。Calcite項目在Hadoop中越來越引人注目,并被衆多項目內建為SQL解析器。

在Apache Kylin一條查詢的執行過程主要分成四個部分:詞法分析、邏輯執行計劃、實體執行計劃和執行。以如下SQL語句為例:

SELECT TEST_CAL_DT.WEEK_BEG_DT, SUM(TEST_KYLIN_FACT.PRICE) FROM TEST_KYLIN_FACT AS FACT
       INNER JOIN EDW.TEST_CAL_DT as DT ON FACT.CAL_DT = DT.CAL_DT 
WHERE FACT.CAL_DT > ‘2017-01-01’
    GROUP TEST_CAL_DT.WEEK_BEG_DT
           

在詞法分析階段,Calcite将該查詢拆分成包含關鍵詞識别的字元段,如圖2-34所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

之後,Calcite根據詞法分析的結果,生成一個邏輯執行計劃,如圖2-35所示。

之後,Calcite會基于規則對邏輯執行計劃進行優化,在優化的過程中根據這些規則将算子轉化為對應的實體執行算子。而Apache Kylin則在其中增加了一些優化政策。首先,在每一個優化規則中将對應的實體算子轉換成Apache Kylin自己的OLAPxxxRel算子。然後根據每一個算子中保持的資訊構造本次查詢的上下文OLAPContext。之後再根據本次查詢中使用的次元列、度量資訊等查詢是否有滿足本次查詢的Cuboid,如果有則将其儲存在OLAPContext的realization中,如圖2-36所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

之後Calcite會根據這個執行計劃動态生成執行代碼。并且根據之前記錄在OLAPContext中的realization資訊,到HBase中讀取相對應的已經建構好的cuboid資料,用以回答查詢,如圖2-37所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

2.6.2 查詢下壓

在Apache Kylin中的查詢,隻有預先針對查詢内的次元和度量進行模組化并建構Cube才能夠回答查詢。是以在Apache Kylin中針對于無法擊中Cube的查詢,便有了另外一種處理方式即查詢下壓。查詢下壓的本質是将無法用Cube回答的查詢路由到Hive或Spark這類查詢引擎,用以回答該查詢。查詢下壓的實作方式如圖2-38所示。

帶你讀《Apache Kylin權威指南》之二:快 速 入 門快 速 入 門

一條查詢經過解析後,進入查詢路由,首先會進入Cube查詢執行器中去尋找是否有能夠回答該查詢的Cube。如果沒有找到合适的Cube,則會抛出異常“No realization found.”,并将這個結果抛回查詢路由,查詢路由檢測到該異常後,則會将該查詢路由到一個外部查詢引擎(如Hive),以回答這條查詢。

2.7 SQL參考

Apache Kylin支援标準SQL查詢語言,但是SQL有很多變體,Apache Kylin支援的隻是SQL所有變體中的一個子集,并不是支援所有現存的SQL語句和文法。使用者在使用Apache Kylin之前,需要對Apache Kylin的SQL支援有一個了解,避免走彎路。

首先,Apache Kylin作為OLAP引擎,隻支援查詢,而不支援其他操作,如插入、更新等,即所有SQL都必須是SELECT語句,否則Apache Kylin會報錯。

第二,在Apache Kylin中進行查詢時,使用SQL語句中的表名、列名、度量、連接配接關系等條件,來比對資料模型和Cube;在設計Cube的時候,就要充分考慮查詢的需求,避免遺漏表、列等資訊。

第三,進行查詢時一條SQL需要首先被Apache Calcite解析,然後才可以被Apache Kylin執行。下面是Calcite中的SELECT語句的文法:

SELECT [ STREAM ] [ ALL | DISTINCT ]
          { * | projectItem [, projectItem ]* }
      FROM tableExpression
      [ WHERE booleanExpression ]
      [ GROUP BY { groupItem [, groupItem ]* } ]
      [ HAVING booleanExpression ]
      [ WINDOW windowName AS windowSpec [, windowName AS windowSpec ]* ]

projectItem:
      expression [ [ AS ] columnAlias ]
  |   tableAlias . *

tableExpression:
      tableReference [, tableReference ]*
  |   tableExpression [ NATURAL ] [ LEFT | RIGHT | FULL ] JOIN tableExpression
[ joinCondition ]

joinCondition:
      ON booleanExpression
  |   USING '(' column [, column ]* ')'           

2.8 小結

本章介紹了使用Apache Kylin前必須了解的基本概念,如星形資料模型、事實表、維表、次元、度量等,并在了解這些基本概念的基礎上快速建立了基于Sample Data的模型,建構Cube,最後執行SQL查詢。帶領讀者體驗了Apache Kylin的主要使用過程。後續章節将繼續展開和探讨這個過程中的一些關鍵技術,比如增量建構、可視化和Cube優化等。