hbase是在一個hdfs上開發的面向列的分布式資料庫。hbase不是關系型資料庫,不支援sql。
htable一些基本概念
row key
行主鍵, hbase不支援條件查詢和order by等查詢,讀取記錄隻能按row key(及其range)或全表掃描,是以row key需要根據業務來設計以利用其存儲排序特性(table按row key字典序排序如1,10,100,11,2)提高性能。
column family(列族)
在表建立時聲明,每個column family為一個存儲單元。在上例中設計了一個hbase表blog,該表有兩個列族:article和author。
column(列)
hbase的每個列都屬于一個列族,以列族名為字首,如列article:title和article:content屬于article列族,author:name和author:nickname屬于author列族。
column不用建立表時定義即可以動态新增,同一column family的columns會群聚在一個存儲單元上,并依column key排序,是以設計時應将具有相同i/o特性的column設計在一個column family上以提高性能。
timestamp
hbase通過row和column确定一份資料,這份資料的值可能有多個版本,不同版本的值按照時間倒序排序,即最新的資料排在最前面,查詢時預設傳回最新版本。如上例中row key=1的author:nickname值有兩個版本,分别為1317180070811對應的“一葉渡江”和1317180718830對應的“yedu”(對應到實際業務可以了解為在某時刻修改了nickname為yedu,但舊值仍然存在)。timestamp預設為系統目前時間(精确到毫秒),也可以在寫入資料時指定該值。
value
每個值通過4個鍵唯一索引,tablename+rowkey+columnkey+timestamp=>value,例如上例中{tablename=’blog’,rowkey=’1’,columnname=’author:nickname’,timestamp=’ 1317180718830’}索引到的唯一值是“yedu”。
存儲類型
tablename 是字元串
rowkey 和 columnname 是二進制值(java 類型 byte[])
timestamp 是一個 64 位整數(java 類型 long)
value 是一個位元組數組(java類型 byte[])。
shell操作
hbase提供了豐富的通路接口,其中hbase shell是常用的便捷方式。
• hbase shell
• java clietn api
• jython、groovy dsl、scala
• rest
• thrift(ruby、python、perl、c++…)
• mapreduce
• hive/pig
建立表
<code>> create 'test','data1','data2'</code>
column family是schema的一部分,而column不是。這裡的data1和data2是column family。
增加記錄
<code>>put 'test','1','data1:name','luc' >put 'test','1','data1:age','24' >put 'test','1','data2:height','170cm' >put 'test','1','data2:weight','65kg' >put 'test','1','data1:nickname','vichao'</code>
column完全動态擴充,每行可以有不同的columns。(ps:好像有點胖啊,要減肥~~)
根據rowkey查詢
<code>> get 'test','1'</code>
htable按rowkey字典序(1,10,100,11,2)自動排序,每行包含任意數量的columns,columns按columnkey(data1:age,data1:name,data1:nickname,data2:height,data2:weight)自動排序。
更新操作
查詢值:
<code>> </code>get 'test','1','data1:nickname'
更新nickname為'vic':
<code>> </code>put 'test','1','data1:nickname','vic'
查詢更新後的結果:(傳回的将是vic)
<code>> get ‘blog’,’1’,’data1:nickname’</code>
知識點回顧:查詢預設傳回最近的值。
查詢nickname的多個(本示例為2個)版本值
<code>> get 'test','1',{column => 'data1:nickname',versions => 2}</code>
知識點回顧:每個column可以有任意數量的values,按timestamp倒序自動排序。
如何隻查詢到以前的舊版本呢,需要借助timestamp
<code>></code>get 'test','1',{column=>'data1:nickname',timestamp=>1373707746997}
知識點回顧:tabelname+rowkey+column+timestamp=>value
删除記錄
delete隻能删除一個column
<code>>delete 'test','1','data1:nickname'</code>
删除rowkey的所有column用deleteall
<code>>deleteall 'test','1'</code>
删除表
練習完畢,把練習表删了吧,删除之前需要先disable
<code>>disable 'test' >drop 'test'</code>
java api操作
javaapi操作還是比較簡單的,各種api類和api函數,直接上代碼了
這裡要注意的一點是連接配接到hbase需要将将hbase環境的hbase-site.xml檔案引入到工程中,就像jdbc的資料庫連接配接一樣,不然是連不上hbase滴。
hbase mapreduce操作
直接上代碼了:
優化
針對行的鍵按資料排列的次序進行随機處理;
每個任務隻執行個體化一個htable對象;
htable.put(put)執行put操作時不使用任何緩沖。可以通過使用htable.setautoflush(false),設定禁用自動刷入,并設定寫緩沖大小,同時在任務的最後設定htable.flushcommits()或者htable.close(),以確定緩沖中最後沒有剩下的未刷入的資料;
設計行鍵的時候要多加考慮,可以使用複合鍵,如果鍵是整數,則應該使用二進制形式以節省存儲空間;
hbase和rdbms的比較
hbase:
hbase是一個分布式的面向列的資料存儲系統;
hbase表可以很高和很寬(數十億行,數百萬列);
水準分區并在數千個商用機節點上自動複制;
表的模式是實體存儲的直接反映;
不支援sql;
不需要強一緻性和參照完整性;
不支援索引;行是順序存儲的,每行中的列也是,不存在索引膨脹的問題,插入性能和表的大小無關
事務好像僅僅支援針對某一行的一系列put/delete操作。不同行、不同表間的操作是無法放在一個事務中的;
hbase不支援條件查詢和order by等查詢,讀取記錄隻能按row key(及其range)或全表掃描;
沒有内置對連接配接操作的支援,但是由于表的寬度可以很大,一個寬行可以容下一個主鍵相關的所有資料,并不需要使用連接配接;
rdbms:
支援sql;
需要強一緻性和參照完整性;
支援事務,索引等;
hbase的特性
沒有索引,行是順序存儲的,每行中的列也是,不存在索引膨脹的問題,插入性能和表的大小無關;
自動分區,在表增長的時候,表會自動分裂成區域,并分布到可用的節點上;
線性擴充和對于新節點的自動處理,增加一個節點,把它指向現有的叢集,并運作regionserver,區域會自動重新進行平衡,負載會均勻分布;
普通商用硬體支援;
容錯,大量節點意味着每個節點的重要性并不突出,不用擔心單個節點失效;
批處理,支援mapreduce操作,可以用全并行的分布式作業來處理資料;