一、前言
近兩年,KUDU 在大資料平台的應用越來越廣泛。在阿裡、小米、網易等公司的大資料架構中,KUDU 都有着不可替代的地位。本文通過分析 KUDU 的設計, 試圖解釋為什麼 KUDU 會被廣泛應用于大資料領域,因為還沒有研究過 KUDU 的代碼,下面的介紹是根據 KUDU 的論文和網上的一些資料學習自己了解所得,如有不實之處,勞請指正。
二、背景
在 KUDU 之前,大資料主要以兩種方式存儲:
- 靜态資料:以 HDFS(如:Hive) 引擎作為存儲引擎,适用于高吞吐量的離線大資料分析場景。這類存儲的局限性是資料無法進行随機的讀寫。不支援單條記錄級别的update操作,随機讀寫性能差。
- 動态資料:以 HBase、Cassandra 作為存儲引擎,适用于大資料随機讀寫場景。這類存儲的局限性是批量讀取吞吐量遠不如 HDFS,不适用于批量資料分析的場景。卻并不适用于基于SQL的資料分析方向,大批量資料擷取時的性能較差。
那為什麼HBase不适合做分析呢?
因為分析需要批量擷取資料,而HBase本身的設計并不适合批量擷取資料
1)HBase是列式資料庫,其實從底層存儲的角度來說它并不是列式的,擷取指定列資料時是會讀到其他列資料的。相對而言Parquet格式針對分析場景就做了很多優化。
2)HBase是LSM-Tree架構的資料庫,這導緻了HBase讀取資料路徑比較長,從記憶體到磁盤,可能還需要讀多個HFile檔案做版本合并。
LSM 的中心思想就是将随機寫轉換為順序寫來大幅提高寫入操作的性能,但是犧牲了部分讀的性能。随機讀寫是指對任意一個位置的讀和寫,磁盤随機讀寫慢是因為需要尋道,倒帶才可以通路到指定存儲點,而記憶體不需要,可以任意指定存儲點。
從上面分析可知,這兩種資料在存儲方式上完全不同,進而導緻使用場景完全不同,但在真實的場景中,邊界可能沒有那麼清晰,面對既需要随機讀寫,又需要批量分析的大資料場景,該如何選擇呢?這個場景中,單種存儲引擎無法滿足業務需求,我們需要通過多種大資料工具組合來滿足這一需求,一個常見的方案是:
滿足資料更新+批量分析的大資料架構
為了讓資料平台同時具備随機讀寫和批量分析能力,傳統的做法是采用混合架構(hybrid architecture),也就是我們常說的T+1的方式,資料實時更新在HBase,第二天淩晨同步到HDFS做離線分析。
如上圖所示,資料實時寫入 HBase,實時的資料更新也在 HBase 完成,為了應對 OLAP 需求,我們定時(通常是 T+1 或者 T+H)将 HBase 資料寫成靜态的檔案(如:Parquet)導入到 OLAP 引擎(如:HDFS),第二天淩晨同步到HDFS做離線分析。這一架構能滿足既需要随機讀寫,又可以支援 OLAP 分析的場景,但他有如下缺點:
這樣的缺點很明顯,時效性差,資料鍊路長,過程複雜,開發成本高。
- 架構複雜。從架構上看,資料在 HBase、消息隊列、HDFS 間流轉,涉及環節太多,運維成本很高。并且每個環節需要保證高可用,都需要維護多個副本,存儲空間也有一定的浪費。最後資料在多個系統上,對資料安全政策、監控等都提出了挑戰。
- 時效性低。資料從 HBase 導出成靜态檔案是周期性的,一般這個周期是一天(或一小時),在時效性上不是很高。
- 難以應對後續的更新。真實場景中,總會有資料是「延遲」到達的。如果這些資料之前已經從 HBase 導出到 HDFS,新到的變更資料就難以處理了,一個方案是把原有資料應用上新的變更後重寫一遍,但這代價又很高。
- 引入實時計算架構如Sparkstreaming、Strom、Flink等計算固化的流量名額,但是這種方式隻能滿足基礎的名額如PV、UV、引導成交等等,且不支援次元下鑽,如果想要新增一種次元就必須走需求評審、開發排期等環節,從需求提出到業務方能看到資料的時間比較久,而且無法滿足使用者在大促期間的臨時取數需求。
- 将Kafka流量流接入Hive,并開發小時級别的離線Hive任務,由于是明細資料,這種方式支援次元的下鑽,對于分析師、産品營運也比較友好。但是小時級别的任務會占用叢集大量的資源,如果上一小時的任務沒有在一小時内跑完就會造成任務追尾的情況出現,這樣下去叢集隻會越來越堵,目前團隊内部已經禁止開發新的小時級任務。
其實第二種方式已經能夠滿足多元度看資料的需求了,隻是基于Hive跑小時級任務實在太消耗資源,而且有延遲的風險,那麼有沒有一種存儲技術具有高吞吐量連續讀取資料的能力,而且也支援低延遲的随機讀寫呢?一般來說這2個要求是互斥的,但是Kudu卻在這2者之間做了很好的平衡。
為了解決上述架構的這些問題,KUDU 應運而生。KUDU 的定位是 「Fast Analytics on Fast Data」,是一個既支援随機讀寫、又支援 OLAP 分析的大資料存儲引擎
KUDU 定位
從上圖可以看出,KUDU 是一個「折中」的産品,在 HDFS 和 HBase 這兩個偏科生中平衡了随機讀寫和批量分析的性能。從 KUDU 的誕生可以說明一個觀點:底層的技術發展很多時候都是上層的業務推動的,脫離業務的技術很可能是「空中樓閣」。
三、概覽
1、資料模型,有表結構
KUDU 的資料模型與傳統的關系型資料庫類似,有表結構,需定義Schema資訊,一個 KUDU 叢集由多個表組成,每個表由多個字段組成,一個表必須指定一個由若幹個(>=1)字段組成的主鍵,如下圖:
KUDU 資料模型
KUDU 表中的每個字段是強類型的,而不是 HBase 那樣所有字段都認為是 bytes。這樣做的好處是可以對不同類型資料進行不同的編碼,節省空間。需在寫入資料前定義好每一列的類型,(友善做類似于parquet的列式存儲)。同時,因為 KUDU 的使用場景是 OLAP 分析,有一個資料類型對下遊的分析工具也更加友好。
2、支援随機讀寫,核心 API
KUDU 的對外 API 主要分為寫跟讀兩部分。其中寫包括:Insert、Update、Delete,所有寫操作都必須指定主鍵;讀 KUDU 對外隻提供了 Scan 操作,Scan 時使用者可以指定一個或多個過濾器,用于過濾資料。
3、一緻性模型,事務管理(ACID),事務4個特征
跟大多數關系型資料庫一樣,KUDU 也是通過 MVCC(Multi-Version Concurrency Control)來實作内部的事務隔離。KUDU 預設的一緻性模型是 Snapshot Consistency,即用戶端可以一緻的通路到某個時間點的一個快照。
如果有更高的外部一緻性(external consistency)需求,KUDU 目前還沒有實作,不過 KUDU 提供了一些設計方案。這裡先介紹下外部一緻性,它是指:多個事務并發執行達到串行效果,并且保證修改時間戳嚴格按照事務發生先後順序,即如果有先後兩個事務 A、B, A 發生在 B 之前,那麼對于用戶端來說,要麼看到 A,要麼看到 A、B,不會隻看到 B 而看不到 A。KUDU 提供了兩個實作外部一緻性的方案:
- 方案一:在各個 Client 之間傳播帶有時間戳的 token,大緻思路是: Client 送出完一個寫請求後,生成一個帶時間戳的 token,然後把這個 token 傳播給其他用戶端,其他用戶端請求的時候可以帶上這個 token。
- 方案二:類似 Google Spanner 的方案,通過 commit-wait 機制實作外部一緻性。
這裡我們衍生介紹下 Google Spanner 是如何實作分布式事務的外部一緻性的。首先我們先明确下分布式事務外部一緻性這個問題的由來。首先,在資料庫中,我們出于性能考慮,一般我們對讀不加排他鎖,隻對寫進行加排他鎖,這就會帶來一個問題,資料在讀取的時候可能正在被修改,導緻同一事務中多次讀取到的資料可能不一緻,為了解決這個問題,我們引入了 MVCC。在單機系統中,通過 MVCC 就能解決外部一緻性問題,因為每個事務都有一個在本機生成的一個時間戳,根據事務的時間戳先後,我們就能判斷出事務發生的先後順序。但是在分布式系統中,要實作外部一緻性就沒有那麼簡單了,核心問題是事務在不同的機器上執行,而不同機器的本地時鐘是有誤差的,是以就算是真實發生的事務順序是 A->B,但是在事務持久化的時候記錄的時間戳可能是 B < A,這時如果一個事務 C 來讀取資料,可能隻讀到 B 而沒有讀到 A。從上面的分析我們可以發現,分布式系統中保證事務的外部一緻性的核心是一個精确的事務版本(時間戳),而最大的難點也在這裡,計算機上的時鐘不是一個絕對精确的時間,它跟标準時間是有一定的随機的誤差的,導緻分布式系統中不同機器之間的時間有偏差。Google Spanner 的解決思路是把不同機器的誤差時間控制在一個很小的确定的範圍内,再配合 commit-wait 機制來實作外部一緻性。
控制時間誤差的方案稱為 TrueTime,它通過硬體(GPS 和原子鐘)和軟體結合,保證擷取到的時間在較小誤差(±4ms)内絕對正确,具體的實作這裡就不展開了,有興趣的同學可以自行找資料研究。TrueTime 對外隻提供 3 個 API,如下:TrueTime API
這裡最主要的 API 是 TT.now(),它範圍目前絕對精确時間的上下界,表示目前絕對精确時間在 TT.now().earliest 和 TT.now().latest 之間。
有了一個有界誤差的 TrueTime 後,就可以通過 commit-wait 機制來實作外部一緻性了,具體的方案如下:
commit-wait 過程
如上圖所示,在一個事務開始擷取鎖執行後,生成事務的時間版本 s=TT.now().latest,然後開始執行事務的具體操作,但是一個事務的結束并不隻由事務本身的時間消耗決定,它還要保證後續的事務時間版本不會早于自己,是以,事務需要等待直到 TT.now().earliest > s 後,才算真正結束。根據整個 commit-wait 過程我們可以知道,整個事務送出過程需要等待 2 倍的平均誤差時間(ε),TrueTime 的平均誤差時間是 4 ms,是以一次 commit-wait 需要至少 8 ms。
之前我們提到,KUDU 也借鑒 Spanner 使用 commit-wait 機制實作外部一緻性,但是 commit-wait 強依賴于 TrueTime,而 TrueTime 需要各種昂貴的硬體裝置支援,目前 KUDU 通過純軟體算法的方式來實作時鐘算法,為 HybridTime,但這個方案時間誤差較大,考慮到 commit-wait 需要等待 2ε 時間,是以誤差一大實際場景使用限制就很多了。
四、架構
整體架構
KUDU 中存在兩個角色
- Mater Server :負責叢集管理、中繼資料管理等功能 (Master節點)
- Tablet Server:負責資料存儲,并提供資料讀寫服務(可對比了解HBase中的RegionServer角色),一個 tablet server 存儲了table表的tablet 和為 tablet 向 client 提供服務。
- Tablet:一個 tablet 是一張 table連續的segment,tablet是kudu表的水準分區(HBase的region)
為了實作分區容錯性,跟其他大資料産品一樣,對于每個角色,在 KUDU 中都可以設定特定數量(一般是 3 或 5)的副本。各副本間通過 Raft 協定來保證資料一緻性。Raft 協定與 ZAB 類似,都是 Paxos 協定的工程簡化版本
KUDU Client 在與服務端互動時,先從 Master Server 擷取中繼資料資訊,然後去 Tablet Server 讀寫資料
資料分區政策
與大多數大資料存儲引擎類似,KUDU 對表進行橫向分區,KUDU 表會被橫向切分存儲在多個 tablets 中。不過相比與其他存儲引擎,KUDU 提供了更加豐富靈活的資料分區政策。
一般資料分區政策主要有兩種,
一、一種是 Range Partitioning,按照字段值範圍進行分區,HBase 就采用了這種方式,如下圖:
Range Partitioning 的優勢是在資料進行批量讀的時候,可以把大部分的讀變成同一個 tablet 中的順序讀,能夠提升資料讀取的吞吐量。并且按照範圍進行分區,我們可以很友善的進行分區擴充。其劣勢是同一個範圍内的資料寫入都會落在單個 tablet 上,寫的壓力大,速度慢。
二、另一種分區政策是 Hash Partitioning,按照字段的 Hash 值進行分區,Cassandra 采用了這個方式,見下圖:
Hash Partitioning
與 Range Partitioning 相反,由于是 Hash 分區,資料的寫入會被均勻的分散到各個 tablet 中,寫入速度快。但是對于順序讀的場景這一政策就不太适用了,因為資料分散,一次順序讀需要将各個 tablet 中的資料分别讀取并組合,吞吐量低。并且 Hash 分區無法應對分區擴充的情況。
各種分區政策的優劣對比見下圖:
各種分區政策的優劣
既然各分區政策各有優劣,能否将不同分區政策進行組合,取長補短呢?這也是 KUDU 的思路,KUDU 支援使用者對一個表指定一個範圍分區規則和多個 Hash 分區規則,如下圖:
組合分區政策
五、存儲
存儲設計目标
- 快速的列掃描
- 低延遲的随機更新
- 穩定的性能表現
存儲方式
KUDU 是一個列式存儲的存儲引擎,其資料存儲方式如下:
KUDU 存儲
列式存儲的資料庫很适合于 OLAP 場景,其特點如下:
- 優勢
- 查詢少量列時 IO 少,速度快
- 資料壓縮比高
- 便于查詢引擎性能優化:延遲物化、直接操作壓縮資料、向量化執行
- 劣勢
- 查詢列太多時性能下降(KUDU 建議列數不超過 300 )
- 不适合 OLTP 場景
存儲實作,資料存儲結構
一張表table會分成若幹個tablet,每個tablet包括MetaData元資訊及若幹個RowSet,RowSet包含一個MemRowSet及若幹個DiskRowSet,DiskRowSet中包含一個BloomFile、Ad_hoc Index、BaseData、DeltaMem及若幹個RedoFile和UndoFile(UndoFile一般情況下隻有一個)。
• MemRowSet:用于新資料insert及已在MemRowSet中的資料的更新,一個MemRowSet寫滿後會将資料刷到磁盤形成若幹個DiskRowSet。每次到達32M生成一個DiskRowSet。
• DiskRowSet:用于老資料的變更(mutation),背景定期對DiskRowSet做compaction,以删除沒用的資料及合并曆史資料,減少查詢過程中的IO開銷。
• BloomFile:根據一個DiskRowSet中的key生成一個bloom filter,用于快速模糊定位某個key是否在DiskRowSet中存在。
• Ad_hocIndex:是主鍵的索引,用于定位key在DiskRowSet中的具體哪個偏移位置。
• BaseData是MemRowSet flush下來的資料,按列存儲,按主鍵有序。
• UndoFile是基于BaseData之前時間的曆史資料,通過在BaseData上apply UndoFile中的記錄,可以獲得曆史資料。
• RedoFile是基于BaseData之後時間的變更(mutation)記錄,通過在BaseData上apply RedoFile中的記錄,可獲得較新的資料。
• DeltaMem用于DiskRowSet中資料的變更mutation,先寫到記憶體中,寫滿後flush到磁盤形成RedoFile。
kudu自己存儲資料不依賴與HDFS存儲;不依賴于zookeeper,将它的功能內建進了自身的TMaster;
與其他大資料存儲引擎類似,KUDU 的存儲也是通過 LSM 樹(Log-Structured Merge Tree)來實作的。LSM 的中心思想就是将随機寫轉換為順序寫來大幅提高寫入操作的性能,但是犧牲了部分讀的性能。
KUDU 的最小存儲單元是 RowSets,KUDU 中存在兩種 RowSets:MemRowSets、DiskRowSets,資料先寫記憶體中的 MemRowSet,MemRowSet 滿了後刷到磁盤成為一個 DiskRowSet,DiskRowSet 一經寫入,就無法修改了。見下圖:
當然上面隻是最粗粒度的一個寫入過程,為了解釋 KUDU 的為什麼既能支援随機讀寫,又能支援大資料量的 OLAP 分析,我們需要更進一步進行解剖分析。我們需求探究的主要兩個問題是:
- 如何應對資料變更?
- 如何優化讀寫性能以滿足 OLAP 場景?
應對資料變更
首先上面我們講了,DiskRowSet 是不可修改了,那麼 KUDU 要如何應對資料的更新呢?在 KUDU 中,把 DiskRowSet 分為了兩部分:base data、delta stores。base data 負責存儲基礎資料,delta stores負責存儲 base data 中的變更資料。整個資料更新方案如下:
應對資料更新
如上圖所示,資料從 MemRowSet 刷到磁盤後就形成了一份 DiskRowSet(隻包含 base data),每份 DiskRowSet 在記憶體中都會有一個對應的 DeltaMemStore,負責記錄此 DiskRowSet 後續的資料變更(更新、删除)。DeltaMemStore 内部維護一個 B-樹索引,映射到每個 row_offset 對應的資料變更。DeltaMemStore 資料增長到一定程度後轉化成二進制檔案存儲到磁盤,形成一個 DeltaFile,随着 base data 對應資料的不斷變更,DeltaFile 逐漸增長。
優化讀寫性能
首先我們從 KUDU 的 DiskRowSet 資料結構上分析:
DiskRowSet 資料結構
從上圖可知,在具體的資料(列資料、變更記錄)上,KUDU 都做了 B- 樹索引,以提高随機讀寫的性能。在 base data 中,KUDU 還針對主鍵做了好幾類索引(實際上由于 delta store 隻記錄變更資料,base data 中對主鍵的索引即本 DiskRowSet 中全局的主鍵索引):
- 主鍵範圍索引:記錄本 DiskRowSet 中主鍵的範圍,用于粗粒度過濾一些主鍵範圍
- 布隆過濾器:通過主鍵的布隆過濾器來實作不存在資料的過濾
- 主鍵索引:要精确定位一個主鍵是否存在,以及具體在 DiskRowSet 中的位置(即:row_offset),通過以 B-樹為資料結構的主鍵索引來快速查找。
随着時間的推移,KUDU 中的小檔案會越來越多,主要包括各個 DiskRowSet 中的 base data,還有每個 base data 對應的若幹份 DeltaFile。小檔案的增多會影響 KUDU 的性能,特别是 DeltaFile 中還有很多重複的資料。為了提高性能,KUDU 會進行定期 compaction,compaction 主要包括兩部分:
- DeltaFile compaction:過多的 DeltaFile 影響讀性能,定期将 DeltaFile 合并回 base data 可以提升性能。在通常情況下,會發生頻繁變更的字段是集中在少數幾個字段中的,而 KUDU 是列式存儲的,是以 KUDU 還在 DeltaFile compaction 時做了優化,檔案合并時隻合并部分變更列到 base data 中對應的列。
- DiskRowSet compaction:除了 DeltaFile,定期将 DiskRowSet 合并也能提升性能,一個原因是合并時我們可以将被删除的資料徹底的删除,而且可以減少同樣 key 範圍内資料的檔案數,提升索引的效率。
當使用者的查詢存在列的過濾條件時,KUDU 還可以在查詢時進行 延遲物化(Lazy Materialization )來提升性能。舉例說明,現在我們有這樣一張表:
使用者的 SQL 是這樣的:
SELECT * FROM tb WHERE sex=‘男’ ADN age > 20
KUDU 中資料查詢過程是這樣的:
- 掃描 sex 列,過濾出要查詢的行 [1,3]
- 掃描 age 列,過濾出要查詢的行 [3,4]
- 過濾條件相交,得到 3
- 真正讀取 id=3 行對應的所有列資訊,組裝
上述查詢中,KUDU 真正需要去實體讀取的資料隻有 id=3 這一行,這樣就減少了 IO 數量。
讀寫過程
資料寫過程
如上圖,當 Client 請求寫資料時,先根據主鍵從 Mater Server 中擷取要通路的目标 Tablets,然後到依次對應的 Tablet 擷取資料。因為 KUDU 表存在主鍵限制,是以需要進行主鍵是否已經存在的判斷,這裡就涉及到之前說的索引結構對讀寫的優化了。一個 Tablet 中存在很多個 RowSets,為了提升性能,我們要盡可能地減少要掃描的 RowSets 數量。首先,我們先通過每個 RowSet 中記錄的主鍵的(最大最小)範圍,過濾掉一批不存在目标主鍵的 RowSets,然後在根據 RowSet 中的布隆過濾器,過濾掉确定不存在目标主鍵的 RowSets,最後再通過 RowSets 中的 B-樹索引,精确定位目标主鍵是否存在。如果主鍵已經存在,則報錯(主鍵重複),否則就進行寫資料(寫 MemRowSet)。
資料更新過程
資料更新的核心是定位到待更新資料的位置,這塊與寫入的時候類似,就不展開了,等定位到具體位置後,然後将變更寫到對應的 delta store 中。
資料讀過程
如上圖,資料讀取過程大緻如下:先根據要掃描資料的主鍵範圍,定位到目标的
Tablets,然後讀取 Tablets 中的 RowSets。在讀取每個 RowSet 時,先根據主鍵過濾要 scan 範圍,然後加載範圍内的 base data,再找到對應的 delta stores,應用所有變更,最後 union 上 MenRowSet 中的内容,傳回資料給 Client。
六、應用案例
這裡介紹一個小米使用 KUDU 的案例。具體的業務場景是這樣的:
收集手機App和背景服務發送的 RPC 跟蹤事件資料,然後建構一個服務監控和問題診斷的工具。
- 高寫入吞吐:每天大于200億條記錄
- 為了能夠盡快定位和解決問題,要求系統能夠查詢最新的資料并能快速傳回結果
- 為了友善問題診斷,要求系統能夠查詢/搜尋明細資料(而不隻是統計資訊)
在使用 KUDU 前,小米的架構是這樣的:
一部分源系統資料是通過Scribe(日志聚合系統)把資料寫到HDFS,另一部分源系統資料直接寫入HBase。然後通過Hive/MR/Spark作業把兩部分資料合并,給離線數倉和 OLAP 分析。
在使用 KUDU 後,架構簡化成了:
從上圖我們可以看到,所有的資料存儲都集中到的 KUDU 一個上,減少了整體的架構複雜度,同時,也大大提升了實時性。
連結:https://www.jianshu.com/p/93c602b637a4
一、kudu與Impala的簡單實踐
1.安裝部署完之後的kudu頁面
2. kudu文法示例
建表語句:
CREATE TABLE pk_inline
(
col1 BIGINT PRIMARY KEY,
col2 STRING,
col3 BOOLEAN
) PARTITION BY HASH(col1) PARTITIONS 2 STORED AS KUDU
TBLPROPERTIES ( 'kudu.num_tablet_replicas' = '1');
通過Impala使用Kudu可以建立内部表和外部表兩種。
- 内部表(Internal Table):事實上是屬于Impala管理的表,當删除時會确确實實地删除表結構和資料。在Impala中建表時,預設建的是内部表。
- 外部表(External Table):不由Impala管理,當删除這個表時,并不能從源位置将其删除,隻是接觸了Kudu到Impala之間對于這個表的關聯關系
CREATE TABLE kaka_first
(
id BIGINT,
name STRING
)
DISTRIBUTE BY HASH INTO 16 BUCKETS
TBLPROPERTIES(
'storage_handler' = 'com.cloudera.kudu.hive.KuduStorageHandler',
'kudu.table_name' = 'kaka_first',
'kudu.master_addresses' = '10.10.245.129:7051',
'kudu.key_columns' = 'id'
);
建表語句中,預設第一個就是Primary Key,是個not null列,在後面的
kudu.key_columns
中列出,這邊至少寫一個。
- storage_handler:選擇通過Impala通路kudu的機制,必須填成
com.cloudera.kudu.hive.KuduStorageHandler
- kudu.table_name:Impala為Kudu建(或者關聯的)的表名
- kudu.master_addresses:Impala需要通路的Kudu master清單
- kudu.key_columns:Primary key清單
插入資料
INSERT INTO kaka_first VALUES (1, "john"), (2, "jane"), (3, "jim");
Impala預設一次同時最多插入1024條記錄,作為一個batch
更新資料
UPDATE kaka_first SET name="bob" where id = 3;
删除資料
DELETE FROM kaka_first WHERE id < 3;
修改表屬性
ALTER TABLE kaka_first RENAME TO employee;
//重命名
ALTER TABLE employee
SET TBLPROPERTIES('kudu.master_addresses' = '10.10.245.135:7051');
//更改kudu master address
ALTER TABLE employee SET TBLPROPERTIES('EXTERNAL' = 'TRUE');
//将内部表變為外部表
一個應用
從MySql導出資料到本地txt
select * from DAYCACHETBL into outfile '/tmp/DAYCACHETBL.txt'
fields terminated by '\t'
lines terminated by '\n';
儲存到hdfs中
/data
目錄下
hdfs dfs -mkdir /data
hdfs dfs -put /tmp/DAYCACHETBL.txt /data
在hive shell中建立hive表
create table DAYCACHETBL (
METERID string,
SOURCEID int,
VB double,
DELTA double,
DTIME string,
UPGUID string,
UPBATCH string,
level string,
YEAR string,
MONTH string,
QUARTER string,
WEEK string,
D_DELTA double
)
ROW FORMAT DELIMITED
fields terminated by '\t'
lines terminated by '\n'
stored as textfile
location '/data';
在impala-shell下建立kudu表
create table DAYCACHETBL2 (
METERID string,
SOURCEID int,
VB double,
DELTA double,
DTIME string,
UPGUID string,
UPBATCH string,
level string,
YEAR string,
MONTH string,
QUARTER string,
WEEK string,
D_DELTA double
)
DISTRIBUTE BY HASH INTO 16 BUCKETS
TBLPROPERTIES(
'storage_handler' = 'com.cloudera.kudu.hive.KuduStorageHandler',
'kudu.table_name' = 'DAYCACHETBL2',
'kudu.master_addresses' = 'kudu1:7051,kudu2:7051,kudu3:7051',
'kudu.key_columns' = 'METERID'
);
将hive表中的内容插入kudu表
insert into DAYCACHETBL2 select * from DAYCACHETBL;
3 表設計
kudu的表具有類似于傳統RDBMS中的表的資料結構。schema設計對于實作Kudu的最佳性能和操作穩定性至關重要。業務場景的多變,對于table來說并不存在一種最好的schema設計。大部分情況下,建立kudu的表需要考慮三個問題:
- 列的設計(column design)
- 主鍵設計(primary key design)
- 分區設計(partitioning design)
比較好的Schema設計應該滿足一下要求:
- 資料的分布和存儲的方式滿足:讀取和寫入操作都可以均勻的分散到tablet servers上(受分區影響)
- tablet将以均勻,可預測的速度增長,并且tablet server的負載将随着時間的推移保持穩定(受分區影響最大)
- 掃描将讀取完成查詢所需的最少資料量。(這主要受主鍵設計的影響,但分區也通過分區修剪發揮作用