HBase是Hadoop的一個子項目,HBase采用了Google BigTable的稀疏的,面向列的數據庫實現方式的理論,建立在hadoop的hdfs上,一方面里用了hdfs的高可靠性和可伸縮行,另外一方面里用了BigTable的高效數據組織形式.可以說HBase為海量數據的real-time相應提供了很好的一個開源解決方案.據說在某運營商中使用類似于BigTable(個人猜測應該就是HBase)的技術可以在兩秒時間內從2TB數據中查找到某條話費記錄.而這是原來該運營商使用Oracle數據庫所無法解決的問題.
對于HBase使用的類似與BigTable的技術我們這里就不仔細描述,可以參考google的論文以及網上的一些相關資料.另外,HBase的配置在HBase的官方文檔中有很詳細的描述.可以參見相關文檔.
HBase提供了一個類似于mysql等關系型數據庫的shell.通過該shell我們可以對HBase的內的相關表以及列族進行控制和處理.HBase shell的help命令比較詳細的列出了HBase所支持的命令.具體使用方法可以參見其文檔.
這里我們用一個學生成績表作為例子,對HBase的基本操作和基本概念進行講解:
下面是學生的成績表:
name grad course:math course:art
Tom 1 87 97
Jerry 2 100 80
這里grad對于表來說是一個列,course對于表來說是一個列族,這個列族由兩個列組成:math和art,當然我們可以根據我們的需要在course中建立更多的列族,如computer,physics等相應的列添加入course列族.
有了上面的想法和需求,我們就可以在HBase中建立相應的數據表啦!
1, 建立一個表格 scores 具有兩個列族grad 和courese
hbase(main):002:0> create 'scores', 'grade', 'course'
0 row(s) in 4.1610 seconds
2,查看當先HBase中具有哪些表
hbase(main):003:0> list
scores
1 row(s) in 0.0210 seconds
3,查看表的構造
hbase(main):004:0> describe 'scores'
{NAME => 'scores', IS_ROOT => 'false', IS_META => 'false', FAMILIES => [{NAME => 'course', BLOOMFILTER => 'false', IN_MEMORY => 'false', LENGTH => '2147483647', BLOCKCACHE => 'false', VERSIONS => '3', TTL => '-1', COMPRESSION => 'NONE'}, {NAME => 'grade', BLOOMFILTER => 'false', IN_MEMORY => 'false', LENGTH => '2147483647', BLOCKCACHE => 'false', VERSIONS => '3', TTL => '-1', COMPRESSION => 'NONE'}]}
1 row(s) in 0.0130 seconds
4, 加入一行數據,行名稱為 Tom 列族grad的列名為”” 值位1
hbase(main):005:0> put 'scores', 'Tom', 'grade:', '1'
0 row(s) in 0.0070 seconds
5,給Tom這一行的數據的列族添加一列 <math,87>
hbase(main):006:0> put 'scores', 'Tom', 'course:math', '87'
0 row(s) in 0.0040 seconds
6,給Tom這一行的數據的列族添加一列 <art,97>
hbase(main):007:0> put 'scores', 'Tom', 'course:art', '97'
0 row(s) in 0.0030 seconds
7, 加入一行數據,行名稱為 Jerry 列族grad的列名為”” 值位2
hbase(main):008:0> put 'scores', 'Jerry', 'grade:', '2'
0 row(s) in 0.0040 seconds
8,給Jerry這一行的數據的列族添加一列 <math,100>
hbase(main):009:0> put 'scores', 'Jerry', 'course:math', '100'
0 row(s) in 0.0030 seconds
9,給Jerry這一行的數據的列族添加一列 <art,80>
hbase(main):010:0> put 'scores', 'Jerry', 'course:art', '80'
0 row(s) in 0.0050 seconds
10,查看scores表中Tom的相關數據
hbase(main):011:0> get 'scores', 'Tom'
COLUMN CELL
course:art timestamp=1224726394286, value=97
course:math timestamp=1224726377027, value=87
grade: timestamp=1224726360727, value=1
3 row(s) in 0.0070 seconds
11,查看scores表中所有數據
hbase(main):012:0> scan 'scores'
ROW COLUMN+CELL
Tom column=course:art, timestamp=1224726394286, value=97
Tom column=course:math, timestamp=1224726377027, value=87
Tom column=grade:, timestamp=1224726360727, value=1
Jerry column=course:art, timestamp=1224726424967, value=80
Jerry column=course:math, timestamp=1224726416145, value=100
Jerry column=grade:, timestamp=1224726404965, value=2
6 row(s) in 0.0410 seconds
12,查看scores表中所有數據courses列族的所有數據
hbase(main):013:0> scan 'scores', ['course:']
ROW COLUMN+CELL
Tom column=course:art, timestamp=1224726394286, value=97
Tom column=course:math, timestamp=1224726377027, value=87
Jerry column=course:art, timestamp=1224726424967, value=80
Jerry column=course:math, timestamp=1224726416145, value=100
4 row(s) in 0.0200 seconds
上面就是HBase的基本shell操作的一個例子,可以看出,hbase的shell還是比較簡單易用的,從中也可以看出HBase shell缺少很多傳統sql中的一些類似于like等相關操作,當然,HBase作為BigTable的一個開源實現,而BigTable是作為google業務的支持模型,很多sql語句中的一些東西可能還真的不需要.
當然,通過程序我們也可以對HBase進行相關的操作.下面的程序就完成了上面shell操作的內容:
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.util.Map;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.io.BatchUpdate;
import org.apache.hadoop.hbase.io.RowResult;
import org.apache.hadoop.hbase.io.Cell;
import org.apache.hadoop.hbase.util.Writables;
public class HBaseBasic {
public static void main(String[] args) throws Exception {
HBaseConfiguration config = new HBaseConfiguration();
HBaseAdmin admin = new HBaseAdmin(config);
if (admin.tableExists("scores")) {
System.out.println("drop table");
admin.disableTable("scores");
admin.deleteTable("scores");
}
System.out.println("create table");
HTableDescriptor tableDescripter = newHTableDescriptor("scores".getBytes());
tableDescripter.addFamily(newHColumnDescriptor("grade:"));
tableDescripter.addFamily(newHColumnDescriptor("course:"));
admin.createTable(tableDescripter);
HTable table = new HTable(config, "scores");
System.out.println("add Tom's data");
BatchUpdate tomUpdate = new BatchUpdate("Tom");
tomUpdate.put("grade:", Writables.getBytes(newIntWritable(1)));
tomUpdate.put("course:math", Writables.getBytes(newIntWritable(87)));
tomUpdate.put("course:art", Writables.getBytes(newIntWritable(97)));
table.commit(tomUpdate);
System.out.println("add Jerry's data");
BatchUpdate jerryUpdate = new BatchUpdate("Jerry");
jerryUpdate.put("grade:", Writables.getBytes(newIntWritable(2)));
jerryUpdate.put("course:math", Writables.getBytes(newIntWritable(100)));
jerryUpdate.put("course:art", Writables.getBytes(newIntWritable(80)));
table.commit(jerryUpdate);
for (RowResult row : table.getScanner(new String[] {"course:" })) {
System.out.format("ROW\t%s\n", newString(row.getRow()));
for (Map.Entry<byte[], Cell> entry : row.entrySet()) {
String column = new String(entry.getKey());
Cell cell = entry.getValue();
IntWritable value = new IntWritable();
Writables.copyWritable(cell.getValue(), value);
System.out.format(" COLUMN\t%s\t%d\n", column, value.get());
}
}
}
}
輸出如下:
drop table
09/07/11 08:51:59 INFO client.HBaseAdmin: Disabled scores
09/07/11 08:51:59 INFO client.HBaseAdmin: Deleted scores
create table
add Tom's data
add Jerry's data
ROW Tom
COLUMN course:art 97
COLUMN course:math 87
ROW Jerry
COLUMN course:art 80
COLUMN course:math 100