HBase有幾個高級特性,在你設計表時可使用。這些特性不必定聯繫到模式或行鍵設計,可是它們定義了某些方面的錶行爲。本節咱們討論這些配置參數,以及你能夠如何使用它們。
1 可配置的數據塊大小
HFile數據塊大小能夠在列族層次設置。這個數據塊不一樣於以前談到的HDFS數據塊。其默認值是65,536字節,或64KB。數據塊索引存儲每一個HFile數據塊的起始鍵。數據塊大小設置影響到數據塊索引的大小。數據塊越小,索引越大,從而佔用更大內存空間。同時由於加載進內存的數據塊更小,隨機查找性能更好。可是若是你須要更好的序列掃描性能,那麼一次可以加載更多HFile數據進入內存則更爲合理,這意味着數據塊應該設置爲更大的值。相應地索引變小,你將在隨機讀性能上付出代價。
你能夠在表實例化時設置數據塊大小,以下所示:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', BLOCKSIZE => '65536'}
2 數據塊緩存
把數據放進讀緩存,但工做負載卻常常不能從中得到性能提高——例如,若是一張表或表裏的列族只被順序化掃描訪問或者不多被訪問,你不會介意Get或Scan花費時間是否有點兒長。在這種狀況下,你能夠選擇關閉那些列族的緩存。若是你只是執行不少順序化掃描,你會屢次倒騰緩存,而且可能會濫用緩存把應該放進緩存得到性能提高的數據給排擠出去。若是關閉緩存,你不只能夠避免上述狀況發生,並且可讓出更多緩存給其餘表和同一表的其餘列族使用。
數據塊緩存默認是打開的。你能夠在新建表或者更改表時關閉它:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', BLOCKCACHE => 'false’}
3 激進緩存
你能夠選擇一些列族,賦予它們在數據塊緩存裏有更高的優先級(LRU緩存)。若是你預期一個列族比另外一個列族隨機讀更多,這個特性早晚用得上。這個配置也是在表實例化時設定:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', IN_MEMORY => 'true'}
IN_MEMORY參數的默認值是false。由於HBase除了在數據塊緩存裏保存這個列族相比其餘列族更激進以外並不提供額外的保證,該參數在實踐中設置爲true不會變化太大。
4 布隆過濾器(Bloom filters)
數據塊索引提供了一個有效的方法,在訪問一個特定的行時用來查找應該讀取的HFile的數據塊。可是它的效用是有限的。HFile數據塊的默認大小是64KB,這個大小不能調整太多。
若是你要查找一個短行,只在整個數據塊的起始行鍵上創建索引沒法給你細粒度的索引信息。例如,若是你的行佔用100字節存儲空間,一個64KB的數據塊包含(64 * 1024)/100 = 655.53 = ~700行,而你只能把起始行放在索引位上。你要查找的行可能落在特定數據塊上的行區間裏,但也不是確定存放在那個數據塊上。這有多種狀況的可能,或者該行在表裏不存在,或者存放在另外一個HFile裏,甚至在MemStore裏。這些狀況下,從硬盤讀取數據塊會帶來IO開銷,也會濫用數據塊緩存。這會影響性能,尤爲是當你面對一個巨大的數據集而且有不少併發讀用戶時。
布隆過濾器容許你對存儲在每一個數據塊的數據作一個反向測試。當某行被請求時,先檢查布隆過濾器看看該行是否不在這個數據塊。布隆過濾器要麼肯定回答該行不在,要麼回答它不知道。這就是爲何咱們稱它是反向測試。布隆過濾器也能夠應用到行裏的單元上。當訪問某列標識符時先使用一樣的反向測試。
布隆過濾器也不是沒有代價。存儲這個額外的索引層次佔用額外的空間。布隆過濾器隨着它們的索引對象數據增加而增加,因此行級布隆過濾器比列標識符級布隆過濾器佔用空間要少。當空間不是問題時,它們能夠幫助你榨乾系統的性能潛力。
你能夠在列族上打開布隆過濾器,以下所示:
hbase(main):007:0> create 'mytable',
{NAME => 'colfam1', BLOOMFILTER => 'ROWCOL'}
BLOOMFILTER參數的默認值是NONE。一個行級布隆過濾器用ROW打開,列標識符級布隆過濾器用ROWCOL打開。行級布隆過濾器在數據塊裏檢查特定行鍵是否不存在,列標識符級布隆過濾器檢查行和列標識符聯合體是否不存在。ROWCOL布隆過濾器的開銷高於ROW布隆過濾器。
5 生存時間(TTL)
應用系統常常須要從數據庫裏刪除老數據。因爲數據庫很難超過某種規模,因此傳統上數據庫內建了許多靈活處理辦法。例如,在TwitBase裏你不肯意刪除用戶在使用應用系統期間生成的任何推帖。這些都是用戶生成數據,未來有一天當你執行一些高級分析時可能有用。可是並不須要保存全部推帖用於實時訪問。因此早於某個時間的推帖能夠歸檔存放到平面文件裏。
HBase可讓你在數秒內在列族級別設置一個TTL。早於指定TTL值的數據在下一次大合併時會被刪除。若是你在同一單元上有多個時間版本,早於設定TTL的版本會被刪除。你能夠關閉TTL或者經過設置其值爲INT.MAX_VALUE (2147483647)來讓它永遠打開(這是默認值)。你能夠在建表時設置TTL,以下所示:
hbase(main):002:0> create 'mytable', {NAME => 'colfam1', TTL => '18000'}
該命令在colfam1列族上設置TTL爲18,000秒=5小時。colfam1裏超過5小時的數據將會在下一次大合併時被刪除。
6 壓縮
HFile能夠被壓縮並存放在HDFS上。這有助於節省硬盤IO,可是讀寫數據時壓縮和解壓縮會擡高CPU利用率。壓縮是表定義的一部分,能夠在建表或模式改變時設定。除非你肯定不會從壓縮中受益,咱們推薦你打開表的壓縮。只有在數據不能被壓縮或者由於某種緣由服務器的CPU利用率有限制要求的狀況下,有可能會關閉壓縮特性。
HBase可使用多種壓縮編碼,包括LZO、Snappy和GZIP。LZO[1]和Snappy[2]是其中最流行的兩種。Snappy由Google在2011年發佈,發佈不久Hadoop和HBase項目開始提供支持。在此以前,選擇的是LZO編碼。Hadoop使用的LZO原生庫受GPLv2版權控制,不能放在Hadoop和Hbase的任何發行版裏;它們必須單獨安裝。另外一方面,Snappy擁有BSD許可(BSD-licensed),因此它更容易和Hadoop和HBase發行版捆綁在一塊兒。LZO和Snappy的壓縮比例和壓縮/解壓縮速度差很少。
當建表時你能夠在列族上打開壓縮,以下所示:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', COMPRESSION => 'SNAPPY'}
注意數據只在硬盤上是壓縮的。在內存裏(MemStore或BlockCache)或網絡傳輸時是沒有壓縮的。
改變壓縮編碼的作法不該該常常發生,可是若是你的確須要改變某個列族的壓縮編碼,直接作就能夠。你須要更改表定義,設定新壓縮編碼。此後合併時,生成的HFile所有會採用新編碼壓縮。這個過程不須要建立新表和複製數據。但你要確保直到改變編碼後全部老HFile被合併後才能從集羣中刪除老編碼函數庫。
7 單元時間版本
HBase在默認狀況下每一個單元維護三個時間版本。這個屬性是能夠設置的。若是你只須要一個版本,推薦你在設置表時只維護一個版本。這樣系統就不會保留更新單元的多個時間版本。時間版本也是在列族級設置的,能夠在表實例化時設定:
hbase(main):002:0> create 'mytable', {NAME => 'colfam1', VERSIONS => 1}
你能夠在同一個create語句裏爲列族指定多個屬性,以下所示:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', VERSIONS => 1, TTL => '18000'}
你也能夠指定列族存儲的最少時間版本數,以下所示:
hbase(main):002:0> create 'mytable', {NAME => 'colfam1', VERSIONS => 5,
MIN_VERSIONS => '1'}
在列族上同時設定TTL也是早晚有用的。若是當前存儲的全部時間版本都早於TTL,至少MIN_VERSION個最新版本會保留下來。這樣確保在你的查詢以及數據早於TTL時有結果返回。
[1] Lempel-Ziv-Oberhumer 壓縮算法:www.oberhumer.com/opensource/lzo/。
[2] Snappy 壓縮函數庫,來自於Google:http://code.google.com/p/snappy/。算法