HBase中CloumnFamily的設計規則

爲何要這樣子作呢? html

HBase自己的設計目標是 支持稀疏表,而 稀疏表一般會有不少列,可是每一行有值的列又比較少。
若是不使用Column Family的概念,那麼有兩種設計方案:
1.把全部列的數據放在一個文件中(也就是傳統的按行存儲)。那麼當咱們想要訪問少數幾個列的數據時,須要遍歷每一行,讀取整個表的數據,這樣子是很低效的。
2.把每一個列的數據單獨分開存在一個文件中(按列存儲)。那麼當咱們想要訪問少數幾個列的數據時,只須要讀取對應的文件,不用讀取整個表的數據,讀取效率很高。然而,因爲稀疏表一般會有不少列,這會致使文件數量特別多,這自己會影響文件系統的效率。
 
而Column Family的提出就是爲了在上面兩種方案中作一個折中。HBase中 將一個Column Family中的列存在一塊兒,而不一樣Column Family的數據則分開
因爲在HBase中Column Family的數量一般很小,同時HBase建議把常常一塊兒訪問的比較相似的列放在同一個Column Family中,這樣就能夠在訪問少數幾個列時,只讀取儘可能少的數據。

優化: redis

   由於一直在作hbase的應用層面的開發,因此體會的比較深的一點是hbase的表結構設計會對系統的性能以及開銷上形成很大的區別,本篇文章先按照hbase表中的rowkey、columnfamily、column、timestamp幾個方面進行一些分析。最後結合分析如何設計一種適合應用的高效表結構。 算法

      一、表的屬性 數據庫

      (1)最大版本數:一般是3,若是對於更新比較頻繁的應用徹底能夠設置爲1,可以快速的淘汰無用數據,對於節省存儲空間和提升查詢速度有效果。不過這類需求在海量數據領域比較小衆。 性能優化

      (2)壓縮算法:能夠嘗試一下最新出爐的snappy算法,相對lzo來講,壓縮率接近,壓縮效率稍高,解壓效率高不少。 數據結構

      (3)inmemory:表在內存中存放,一直會被忽略的屬性。若是徹底將數據存放在內存中,那麼hbase和如今流行的內存數據庫memorycached和redis性能差距有多少,尚待實測。 app

      (4)bloomfilter:根據應用來定,看須要精確到rowkey仍是column。不過這裏須要理解一下原理,bloomfilter的做用是對一個region下查找記錄所在的hfile有用。即若是一個region下的hfile數量不少,bloomfilter的做用越明顯。適合那種compaction趕不上flush速度的應用。 負載均衡

      二、rowkey ide

       rowkey是hbase的key-value存儲中的key,一般使用用戶要查詢的字段做爲rowkey,查詢結果做爲value。能夠經過設計知足幾種不一樣的查詢需求。 oop

      (1)數字rowkey的從大到小排序:原生hbase只支持從小到大的排序,這樣就對於排行榜一類的查詢需求很尷尬。那麼採用rowkey = Integer.MAX_VALUE-rowkey的方式將rowkey進行轉換,最大的變最小,最小的變最大。在應用層再轉回來便可完成排序需求。

      (2)rowkey的散列原則:若是rowkey是相似時間戳的方式遞增的生成,建議不要使用正序直接寫入rowkey,而是採用reverse的方式反轉rowkey,使得rowkey大體均衡分佈,這樣設計有個好處是能將regionserver的負載均衡,不然容易產生全部新數據都在一個regionserver上堆積的現象,這一點還能夠結合table的預切分一塊兒設計。

      三、columnfamily

      columnfamily儘可能少,緣由是過多的columnfamily之間會互相影響。

      四、column

      對於column須要擴展的應用,column能夠按普通的方式設計,可是對於列相對固定的應用,最好採用將一行記錄封裝到一個column中的方式,這樣可以節省存儲空間。封裝的方式推薦protocolbuffer。

     

     如下會分場景介紹一些特殊的表結構設計方法,只是一些摸索,歡迎討論:

      value數目過多場景下的表結構設計:

       目前我碰到了一種key-value的數據結構,某一個key下面包含的column不少,以至於客戶端查詢的時候oom,bulkload寫入的時候oom,regionsplit的時候失敗這三種後果。一般來說,hbase的column數目不要超過百萬這個數量級。在官方的說明和我實際的測試中都驗證了這一點。

       有兩種思路能夠參考,第一種是單獨處理這些特殊的rowkey,第二種以下:

      能夠考慮將column設計到rowkey的方法解決。例如原來的rowkey是uid1,,column是uid2,uid3...。從新設計以後rowkey爲<uid1>~<uid2>,<uid1>~<uid3>...固然你們會有疑問,這種方式如何查詢,若是要查詢uid1下面的全部uid怎麼辦。這裏說明一下hbase並非只有get一種隨機讀取的方法。而是含有scan(startkey,endkey)的掃描方法,而這種方法和get的效率至關。須要取得uid1下的記錄只須要new Scan("uid1~","uid1~~")便可。

       這裏的設計靈感來自於hadoop world大會上的一篇文章,這篇文章自己也很棒,推薦你們看一下http://www.cloudera.com/resource/hadoop-world-2011-presentation-slides-advanced-hbase-schema-design/

其餘參考資料:

HBase性能優化方法總結(一):表的設計

http://www.cnblogs.com/panfeng412/archive/2012/03/08/hbase-performance-tuning-section1.html

關於cloumn family的描述:不要在一張表裏定義太多的column family。目前Hbase並不能很好的處理超過2~3個column family的表。由於某個column family在flush的時候,它鄰近的column family也會因關聯效應被觸發flush,最終致使系統產生更多的I/O。

相關文章
相關標籤/搜索