Hbase表結構設計
圖片來自HBase企業應用…書籍
1 模式建立
1.1 hbase模式結構
Hbase的模式結構包括表、RowKey、列族、Timestamp(時間版本)。其真實模式是一個三維有序結構,前面三個維度確定一行資料。 Hbase的模式不同於關係型資料庫(RDBMS),Hbase的單元格(cell)所在行是有序的,其列(Qualifier)在所屬列族(column family)存在的情況下 ,可以通過客戶端自由新增。對於這些名詞具體含義可以參考另一篇博主寫的部落格 http://blog.csdn.net/wulantian/article/details/46786413 我們在設計HBase時候需要考慮不少因素: 1.這個表應該有多少個列族; 2.列粗使用什麼資料; 3.每個列族應該有多少列; 4.列名是什麼; 5.單元應該存放什麼資料; 6.每個單元儲存多少個時間版本; 7.行健(RowKey)結構是什麼。應該包含什麼資訊。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
1.2 HBase設計需要注意兩個關鍵點:
(1)join Hbase沒有join的概念,所以不支援join的操作,但是在不少業務中確需要不少的join操作。而大表結構可以解決這一問題,值需要一條行記錄加上一個特定的行關鍵字,就可以實現把所有的關於join的資料合併在一起。 (2)RowKey RowKey是非常重要的,設計時候需要慎重考慮。如果RowKey是整形的,用二進位制的方式應該比string來儲存一個數據更加節約空間。以儲存使用者購買商品為例,複合的RowKey由使用者Id作為字首,倒置的時間串作為RowKey的字尾可以使得我們瞭解使用者最新購買消費資訊,我們可以根絕這些推薦使用者最近需要什麼的產品,經常使用的推薦演算法,我們可以根據使用者最近的消費商品推薦使用者最近還需要購買什麼產品。
- 1
- 2
- 3
- 4
2 RowKey設計根據實際情況選擇優化以下幾點
2.1 RowKey按字典順序從大到小排序
關係型資料庫可以在多列上建立索引,但是HBase只能在RowKeya上面建立索引。RowKey是不可分割的位元組數,按字典順序由低到高儲存在表中。一個空的陣列用來標識空間的起始或者結尾。但是如果我們需要由大到小排列時候我們可以進行轉換,最大的變最小,最小的變最大,在應用層轉回來即可完成,採用RowKey=Integer.MAX_VALUE-RowKey方式轉換。
- 1
2.2 RowKey儘量雜湊設計
最重要的就是雜湊的保證,這樣就可以保證所有資料都不是在一個Region上,從而避免讀寫時候負載會集中在個別Region上。假設我們需要儲存一個視訊網站使用者的所有觀影記錄,這時候的RowKey可以設計成userId_videoId的拼接字串,但是這樣設計的話userId的分佈就很肯能不均勻,因為RowKey是按字串排序的:我們可以採取三種辦法解決具體如下: (1)反轉userId,將其字串反轉後儲存; (2)雜湊userId,即對userId進行雜湊; (3)userId取模後MD5加密,取前6位作為字首加入到userId前面。
- 1
- 2
- 3
- 4
2.3 Rowkey的長度儘量要短
如果RowKey過長,第一儲存開銷會增加,影響儲存效率;第二記憶體中Rowkey欄位過長,會導致記憶體的利用率過低,進而降低索引命中率。一般做法:時間使用Long表示;儘量使用編碼壓縮。
- 1
3 列族(Column Family)
主要講一下列族的相關配置屬性,這些都是有預設值的,在建立表的時候我們也可以顯示的指定。列族是一些列的集合。一個列族的所有成員都有著相同的字首。比如列course:computer和course:english都是列族的成員。:是用來區分字首跟列名的,列族在建立表時候必須 宣告但是列不需要特別宣告,使用者可以隨時建立新列。一個列族的成員在檔案系統都儲存在一起,因為儲存優化針對的是列族。目前HBase不能很好地處理多個列族。
好了下面該說一下列族的相關配置屬性了。
3.1 可配置的資料塊大小:
HFile資料塊大小可以在列族層設定,其預設值是65536位元組或者64KB,資料塊索引儲存每個HFile資料塊的起始鍵,資料塊越小索引越大,隨機查詢效能更好,程式碼如下:
hbase(main):002:0> create 'mytable'
{NAME =>'colfam1',BLOCKSIZE=>'65536'}
- 1
- 2
3.2 資料塊快取:
資料塊快取預設是開啟的,可以在新建表或者更改表時候關閉資料塊快取屬性,程式碼如下:
- 1
hbase(main):002:0>create'mytable', {NAME=>'colfam1',BLOCKCACHE=>'false'}
- 1
IN_MEMORY引數預設值是false,該值表示HBase除了在資料塊快取中儲存這列族相比其他列族更激進之外,並不提供其他額外保證,下面展示如何設定的程式碼:
- 1
hbase(main):002:0>create'mytable', {NAME=>'colfam1',IN_MEMORY=>'true'}
- 1
3.3 布隆過濾器
資料塊索引提供了一個有效的方法getDataBlockIndexReader(),在訪問某個特定的行時候,用來查詢讀取的HFile的資料塊,但是作用有限。布隆過濾器(Bloom Filter)允許對儲存在每個資料塊的資料做一個反向測驗,當查詢某行時先查詢布隆過濾器,看看改行是否不在這個資料塊,布隆過濾器的兩種回答:1,確定的回答行不在;2:不知道。布隆過濾器也可以應用到行內的單元格上,當訪問某列的識別符號時候先使用同樣的反向檢驗。可以在列族上開啟布隆過濾器,預設值是NONE,另外還有兩個值ROW表示行級布隆過濾器;ROWCOL表示列識別符號級布隆過濾器,程式碼如下:
hbase(main):002:0>create'mytable', {NAME=>'colfam1',BLOOMFILTER =>'ROWCOL'}
- 1
3.4 資料壓縮
HBase可以使用多種壓縮編碼,包括LZO、SNAPPY、GZIP。只在硬碟壓縮,記憶體中或者網路傳輸中沒有壓縮
hbase(main):002:0>create'mytable', {NAME=>'colfam1',COMPRESSION=>'SNAPPY'}
- 1
- 2
3.5 單元時間版本
時間版本是在列族級設定的,只需要一個時間版本時候,這樣子就不會保留更新單元的多個時間版本,程式碼如下:
hbase(main):002:0>create'mytable', {NAME=>'colfam1',VERSIONS=>1}
- 1
最小時間版本數,程式碼如下:
hbase(main):002:0>create'mytable', {NAME=>'colfam1',VERSIONS=>5,MIN_VERSIONS => '1'}
- 1
- 2
同一個建表語句中為列族指定多個屬性程式碼如下:
hbase(main):002:0>create'mytable', {NAME=>'colfam1',VERSIONS => 5,TTL=>'18000'}
- 1
- 2
3.6 生存時間
用於設定單元格的生存週期,單元格過滿則會將其刪除,在列族cf1上設定TTL為18000s,cf1中超過時間的將會在下一次大合併時候刪除。程式碼如下:
hbase(main):002:0>create'mytable', {NAME=>'colfam1',TTL => '18000'}
- 1