HBase是三維有序存儲的,通過rowkey(行鍵),column key(column family和qualifier)和TimeStamp(時間戳)這個三個維度可以對HBase中的數據進行快速定位。
HBase中rowkey可以唯一標識一行記錄,在HBase查詢的時候,有三種方式:
- 通過get方式,指定rowkey獲取唯一一條記錄
- 通過scan方式,設置startRow和stopRow參數進行范圍匹配
- 全表掃描,即直接掃描整張表中所有行記錄
一、 rowkey長度原則
rowkey是一個二進制碼流,可以是任意字符串,最大長度64kb,實際應用中一般為10-100bytes,以byte[]形式保存,一般設計成定長。
建議越短越好,不要超過16個字節(jié),原因如下:
- 數據的持久化文件HFile中是按照KeyValue存儲的,如果rowkey過長,比如超過100字節(jié),1000w行數據,光rowkey就要占用100*1000w=10億個字節(jié),將近1G數據,這樣會極大影響HFile的存儲效率;
- MemStore將緩存部分數據到內存,如果rowkey字段過長,內存的有效利用率就會降低,系統(tǒng)不能緩存更多的數據,這樣會降低檢索效率。
- 目前操作系統(tǒng)都是64位系統(tǒng),內存8字節(jié)對齊,控制在16個字節(jié),8字節(jié)的整數倍利用了操作系統(tǒng)的最佳特性。
二、rowkey散列原則
如果rowkey按照時間戳的方式遞增,不要將時間放在二進制碼的前面,建議將rowkey的高位作為散列字段,由程序隨機生成,低位放時間字段,這樣將提高數據均衡分布在每個RegionServer,以實現負載均衡的幾率。如果沒有散列字段,首字段直接是時間信息,所有的數據都會集中在一個RegionServer上,這樣在數據檢索的時候負載會集中在個別的RegionServer上,造成熱點問題,會降低查詢效率。
三、rowkey唯一原則
必須在設計上保證其唯一性,rowkey是按照字典順序排序存儲的,因此,設計rowkey的時候,要充分利用這個排序的特點,將經常讀取的數據存儲到一塊,將最近可能會被訪問的數據放到一塊。
四、避免熱點
HBase中的行是按照rowkey的字典順序排序的,這種設計優(yōu)化了scan操作,可以將相關的行以及會被一起讀取的行存取在臨近位置,便于scan。然而糟糕的rowkey設計是熱點的源頭。
熱點發(fā)生在大量的client直接訪問集群的一個或極少數個節(jié)點(訪問可能是讀,寫或者其他操作)。大量訪問會使熱點region所在的單個機器超出自身承受能力,引起性能下降甚至region不可用,這也會影響同一個RegionServer上的其他region,由于主機無法服務其他region的請求。設計良好的數據訪問模式以使集群被充分,均衡的利用。
為了避免寫熱點,設計rowkey使得不同行在同一個region,但是在更多數據情況下,數據應該被寫入集群的多個region,而不是一個。
最常用的避免熱點的方法是時間戳反轉,比如 Long.Max_Value - timestamp 得到的值就能均勻散列開來。
五、其他建議
盡量減少行和列的大小
在HBase中,value永遠和它的key一起傳輸的。當具體的值在系統(tǒng)間傳輸時,它的rowkey,列名,時間戳也會一起傳輸。如果你的rowkey和列名很大,甚至可以和具體的值相比較,那么你將會遇到一些有趣的問題。HBase storefiles中的索引(有助于隨機訪問)最終占據了HBase分配的大量內存,因為具體的值和它的key很大??梢栽黾觔lock大小使得storefiles索引再更大的時間間隔增加,或者修改表的模式以減小rowkey和列名的大小。壓縮也有助于更大的索引。列族盡可能越短越好,最好是一個字符
冗長的屬性名雖然可讀性好,但是更短的屬性名存儲在HBase中會更好