进入HBase shell的命令:./hbase shell
HBase的基本操作如下表所示
一、创建表
1、shell操作
相关shell操作如下所示:
- 显示HBase中的所有表
- 创建表(指定命名空间、包含列族c1)
- 创建表(默认命名空间、包含列族c1和c2)
2、Java API
Configuration conf = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(conf);
admin.createNamespace(NamespaceDescriptor.create("ns").build();
//create tableDesc, with namespace name "ns" and table name "table02"
HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf("ns:table02"));
tableDesc.setDurability(Durability.SYNC_WAL);
//设置一个Region中的Store文件的最大size
tableDesc.setMaxFileSize(512);
//设置Region内存中的memstore的最大值
tableDesc.setMemStoreFlushSize(512);
//设置写WAL日志的级别
tableDesc.setDurability(Durability.SYNC_WAL);
//add a column family "mycf"
HColumnDescriptor hcd = new HColumnDescriptor("cf");
//设置数据保存的最大时间
hcd.setTimeToLive(5184000);
//设置数据保存在内存中以提高响应速度
hcd.setInMemory(true);
//设置数据保存的最大版本数
hcd.setMaxVersions(10);
//设置数据保存的最小版本数(配合TimeToLive使用)
hcd.setMinVersions(5);
tableDesc.addFamily(hcd);
admin.createTable(tableDesc);
admin.close();
注意以下几点:
- 可以通过HTableDescriptor对象设置表的特性。
- 由于HBase的数据是先写入内存,数据累计达到内存阀值时才往磁盘中flush数据,所以,如果在数据还没有flush进硬盘时,Region Server down掉了,内存中的数据将丢失。要想解决这个场景的问题就需要用到WAL(Write-Ahead-Log),可以设置写WAL日志的级别,示例中设置的是同步写WAL,该方式安全性较高,但无疑会一定程度影响性能,请根据具体场景选择使用;
- 可以通过HColumnDescriptor对象设置列族的特性。更多特性请自行查阅官网API;
- 数据的版本数只能通过HColumnDescriptor对象设置,不能通过HTableDescriptor对象设置;
- setDurability(Durability d)方法可以在相关的三个对象中使用,分别是:HTableDescriptor,Delete,Put(其中Delete和Put的该方法都是继承自父类org.apache.hadoop.hbase.client.Mutation)。分别针对表插入操作、删除操作设定WAL日志写入级别。需要注意的是,Delete和Put并不会继承Table的Durability级别。Durability是一个枚举变量。如果不通过该方法指定WAL日志级别,则为默认USE_DEFAULT级别。
二、删除表
1、shell操作
删除表之前需要先disable表。
相关shell操作如下所示:
- disable表
- 在1步骤后,删除表
2、Java API
Configuration conf = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(conf);
String tablename = "ns:table02";
if(admin.tableExists(tablename)) {
try {
admin.disableTable(tablename);
admin.deleteTable(tablename);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
admin.close();
三、新增、删除列族
1、shell操作
相关shell操作
- 创建一张表,含有四个列族
- 删除列族newcf
- 删除列族note、susinfo并新增列族action_log
- 显示该表的信息,可以发现该表现有info和action_info两个列族
2、Java API
Configuration conf = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(conf);
String tablename = "ns:table02";
if(admin.tableExists(tablename)) {
try {
admin.disableTable(tablename);
//get the TableDescriptor of target table
HTableDescriptor newtd = admin.getTableDescriptor(Bytes.toBytes("ns:table02"));
//remove 3 useless column families
newtd.removeFamily(Bytes.toBytes("note"));
newtd.removeFamily(Bytes.toBytes("newcf"));
newtd.removeFamily(Bytes.toBytes("susinfo"));
//create HColumnDescriptor for new column family
HColumnDescriptor newhcd = new HColumnDescriptor("action_log");
newhcd.setMaxVersions(10);
newhcd.setKeepDeletedCells(true);
//add the new column family(HColumnDescriptor) to HTableDescriptor
newtd.addFamily(newhcd);
//modify target table struture
admin.modifyTable(Bytes.toBytes("ns:table02"),newtd);
admin.enableTable(tablename);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
admin.close();
流程如下:
- 通过admin.getTableDescriptor(Bytes.toBytes(“ns:table02”))取得目标表的描述对象,取得指向该对象的指针了。
- 修改目标表描述对象。
- 通过admin.modifyTable(Bytes.toBytes(“ns:table02”),newtd)将修改后的描述对象应用到目标表。
四、修改现有列族属性
1、shell操作
相关shell操作如下:
- 查询表ns:table02的信息
- 将info列族的最大版本数修改为100
- 查询修改后的列族信息
五、新增、更新数据Put
1、常用构造函数
- 指定行键
public Put(byte[] row)
参数:row 行键 - 指定行键和时间戳
public Put(byte[] row, long ts)
参数:row 行键,ts 时间戳 - 从目标字符串中提取子串,作为行键
Put(byte[] rowArray, int rowOffset, int rowLength)
参数:rowArray目标字符串,rowOffset起始位置,rowLength长度 - 从目标字符串中提取子串,作为行键,并加上时间戳
Put(byte[] rowArray, int rowOffset, int rowLength, long ts)
2、常用方法
- 指定列族、限定符,添加值
add(byte[] family, byte[] qualifier, byte[] value) - 指定列族、限定符、时间戳,添加值
add(byte[] family, byte[] qualifier, long ts, byte[] value) - 设置写WAL(Write-Ahead-Log)的级别
public void setDurability(Durability d)
参数是一个枚举值,可以有以下几种选择:
ASYNC_WAL : 当数据变动时,异步写WAL日志
SYNC_WAL : 当数据变动时,同步写WAL日志
FSYNC_WAL : 当数据变动时,同步写WAL日志,并且,强制将数据写入磁盘
SKIP_WAL : 不写WAL日志
USE_DEFAULT : 使用HBase全局默认的WAL写入级别,即SYNC_WAL
3、shell操作
- 向ns:table02表中插入信息,行健为rk0001,列族info中添加name列标示符,值为zhangsan
- 向ns:table02表中插入信息,行健为rk0001,列族info中添加gender列标示符,值为female
- 向ns:table02表中插入信息,行健为rk0001,列族info中添加age列标示符,值为20
- 向ns:table02表中插入信息,行健为rk0001,列族action_log中添加pic列标示符,值为picture
- 扫描表ns:table02
4、Java API
插入行
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "ns:table02");
Put put = new Put(Bytes.toBytes("100001"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("name"),Bytes.toBytes("lion"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("address"), Bytes.toBytes("shangdi"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("30"));
put.setDurability(Durability.SYNC_WAL);
table.put(put);
table.close();
更新行
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Put put = new Put(Bytes.toBytes("100001"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("lee"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("address"), Bytes.toBytes("longze"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("31"));
put.setDurability(Durability.SYNC_WAL);
table.put(put);
table.close();
从目标字符串中提取子串,作为行键,构建Put
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Put put = new Put(Bytes.toBytes("100001_100002"),7,6);
put.add(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("show"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("address"), Bytes.toBytes("caofang"));
put.add(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("30"));
table.put(put);
table.close();
注意以下几点:
- Put的构造函数都需要指定行键,如果是全新的行键,则新增一行;如果是已有的行键,则更新现有行。
- 创建Put对象及put.add过程都是在构建一行的数据,创建Put对象时相当于创建了行对象,add的过程就是往目标行里添加cell,直到table.put才将数据插入表格。
- 以上代码创建Put对象用的是构造函数1,也可用构造函数2,第二个参数是时间戳。
- Put还有别的构造函数,请查阅官网API。
六、删除数据
Delete类用于删除表中的一行数据,通过HTable.delete来执行该动作。
在执行Delete操作时,HBase并不会立即删除数据,而是对需要删除的数据打上一个“墓碑”标记,直到当Storefile合并时,再清除这些被标记上“墓碑”的数据。
如果希望删除整行,用行键来初始化一个Delete对象即可。如果希望进一步定义删除的具体内容,可以使用以下这些Delete对象的方法:
- 为了删除指定的列族,可以使用deleteFamily。
- 为了删除指定列的多个版本,可以使用deleteColumns。
- 为了删除指定列的指定版本,可以使用deleteColumn,这样的话就只会删除版本号(时间戳)与指定版本相同的列。如果不指定时间戳,默认只删除最新的版本。
1、构造函数
- 指定要删除的行键
Delete(byte[] row)
删除行键指定行的数据。如果没有进一步的操作,使用该构造函数将删除行键指定的行中所有列族中所有列的所有版本! - 指定要删除的行键和时间戳
Delete(byte[] row, long timestamp)
删除行键和时间戳共同确定行的数据。如果没有进一步的操作,使用该构造函数将删除行键指定的行中,所有列族中所有列的时间戳小于等于指定时间戳的数据版本。
注意:该时间戳仅仅和删除行有关,如果需要进一步指定列族或者列,你必须分别为它们指定时间戳。 - 给定一个字符串,目标行键的偏移,截取的长度
Delete(byte[] rowArray, int rowOffset, int rowLength) - 给定一个字符串,目标行键的偏移,截取的长度,时间戳
Delete(byte[] rowArray, int rowOffset, int rowLength, long ts)
2、常用方法
- Delete deleteColumn(byte[] family, byte[] qualifier) :删除指定列的最新版本的数据。
- Delete deleteColumns(byte[] family, byte[] qualifier):删除指定列的所有版本的数据。
- Delete deleteColumn(byte[] family, byte[] qualifier, long timestamp):删除指定列的指定版本的数据。
- Delete deleteColumns(byte[] family, byte[] qualifier, long timestamp) :删除指定列的,时间戳小于等于给定时间戳的所有版本的数据。
- Delete deleteFamily(byte[] family):删除指定列族的所有列的所有版本数据。
- Delete deleteFamily(byte[] family, long timestamp):删除指定列族的所有列中时间戳小于等于指定时间戳的所有数据。
- Delete deleteFamilyVersion(byte[] family, long timestamp):删除指定列族中所有列的时间戳等于指定时间戳的版本数据。
- void setTimestamp(long timestamp):为Delete对象设置时间戳。
3、shell操作
相关shell操作如下:
- 删除ns:table02表中行键为rk0001,列标示符为info:name的数据
4、Java API
删除整行的所有列族、所有行、所有版本
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Delete delete = new Delete(Bytes.toBytes("000"));
table.delete(delete);
table.close();
删除指定列的最新版本
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Delete delete = new Delete(Bytes.toBytes("100003"));
delete.deleteColumn(Bytes.toBytes("info"),Bytes.toBytes("address"));
table.delete(delete);
table.close();
删除指定列的所有版本
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Delete delete = new Delete(Bytes.toBytes("100003"));
delete.deleteColumns(Bytes.toBytes("info"),Bytes.toBytes("address"));
table.delete(delete);
table.close();
删除指定列族中所有列的时间戳等于指定时间戳的版本数据
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Delete delete = new Delete(Bytes.toBytes("100003"));
delete.deleteFamilyVersion(Bytes.toBytes("info"),1405390959464L);
table.delete(delete);
table.close();
七、获取单行Get
如果希望获取整行数据,用行键初始化一个Get对象就可以,如果希望进一步缩小获取的数据范围,可以使用Get对象的以下方法:
- 如果希望取得指定列族的所有列数据,使用addFamily添加所有的目标列族即可;
- 如果希望取得指定列的数据,使用addColumn添加所有的目标列即可;
- 如果希望取得目标列的指定时间戳范围的数据版本,使用setTimeRange;
- 如果仅希望获取目标列的指定时间戳版本,则使用setTimestamp;
- 如果希望限制每个列返回的版本数,使用setMaxVersions;
- 如果希望添加过滤器,使用setFilter
1、构造函数
Get(byte[] row)
参数是行键
2、常用方法
- Get addFamily(byte[] family):指定希望获取的列族。
- Get addColumn(byte[] family, byte[] qualifier):指定希望获取的列。
- Get setTimeRange(long minStamp, long maxStamp):设置获取数据的时间戳范围。
- Get setTimeStamp(long timestamp):设置获取数据的时间戳。
- Get setMaxVersions(int maxVersions):设定获取数据的版本数。
- Get setMaxVersions():设定获取数据的所有版本。
- Get setFilter(Filter filter):为Get对象添加过滤器,过滤器详解请参见:http://blog.csdn.net/u010967382/article/details/37653177
- void setCacheBlocks(boolean cacheBlocks):设置该Get获取的数据是否缓存在内存中。
3、shell操作
4、Java API
获取行键指定行的所有列族、所有列的最新版本数据
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Get get = new Get(Bytes.toBytes("100003"));
Result r = table.get(get);
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell)));
}
table.close();
获取行键指定行中,指定列的最新版本数据
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Get get = new Get(Bytes.toBytes("100003"));
get.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
Result r = table.get(get);
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell)));
}
table.close();
获取行键指定的行中,指定时间戳的数据
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:leetable");
Get get = new Get(Bytes.toBytes("100003"));
get.setTimeStamp(1405407854374L);
Result r = table.get(get);
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell)));
}
table.close();
获取行键指定的行中,所有版本的数据
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:itable");
Get get = new Get(Bytes.toBytes("100003"));
get.setMaxVersions();
Result r = table.get(get);
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell))+ " Time : " + cell.getTimestamp());
}
table.close();
八、获取多行Scan
Scan对象可以返回满足给定条件的多行数据。如果希望获取所有的行,直接初始化一个Scan对象即可。如果希望限制扫描的行范围,可以使用以下方法:
- 如果希望获取指定列族的所有列,可使用addFamily方法来添加所有希望获取的列族。
- 如果希望获取指定列,使用addColumn方法来添加所有列。
- 通过setTimeRange方法设定获取列的时间范围。
- 通过setTimestamp方法指定具体的时间戳,只返回该时间戳的数据。
- 通过setMaxVersions方法设定最大返回的版本数。
- 通过setBatch方法设定返回数据的最大行数。
- 通过setFilter方法为Scan对象添加过滤器,过滤器详解请参见:http://blog.csdn.net/u010967382/article/details/37653177。
- Scan的结果数据是可以缓存在内存中的,可以通过getCaching()方法来查看当前设定的缓存条数,也可以通过setCaching(int caching)来设定缓存在内存中的行数,缓存得越多,以后查询结果越快,同时也消耗更多内存。此外,通过setCacheBlocks方法设置是否缓存Scan的结果数据块,默认为true。
- 我们可以通过setMaxResultSize(long)方法来设定Scan返回的结果行数。
1、常用构造函数
- 创建扫描所有行的Scan
Scan() - 创建Scan,从指定行开始扫描
Scan(byte[] startRow)
参数:startRow行键
注意:如果指定行不存在,从下一个最近的行开始。 - 创建Scan,指定起止行
Scan(byte[] startRow, byte[] stopRow)
参数:startRow起始行,stopRow终止行
注意:startRow <= 结果集 < stopRow。 - 创建Scan,指定起始行和过滤器
Scan(byte[] startRow, Filter filter)
参数:startRow起始行,filter过滤器。
2、常用方法
- Scan setStopRow(byte[] stopRow):设置Scan的结束行,默认结果集不包含该行。如果希望结果集包含该行,可以在行键末尾加上0。
- Scan setTimeRange(long minStamp, long maxStamp):扫描指定时间范围的数据。
- Scan setTimeStamp(long timestamp):扫描指定时间的数据。
- Scan addColumn(byte[] family, byte[] qualifier):指定扫描的列。
- Scan addFamily(byte[] family):指定扫描的列族。
- Scan setFilter(Filter filter):为Scan设置过滤器。
- Scan setReversed(boolean reversed):设置Scan的扫描顺序,默认是正向扫描(false),可以设置为逆向扫描(true)。注意:该方法0.98版本以后才可用!!
- Scan setMaxVersions():获取所有版本的数据。
- Scan setMaxVersions(int maxVersions):设置获取的最大版本数。
- void setCaching(int caching):设定缓存在内存中的行数,缓存得越多,以后查询结果越快,同时也消耗更多内存。
- void setRaw(boolean raw):激活或者禁用raw模式。如果raw模式被激活,Scan将返回所有已经被打上删除标记但尚未被真正删除的数据。该功能仅用于激活了KEEP_DELETED_ROWS的列族,即列族开启了hcd.setKeepDeletedCells(true)。Scan激活raw模式后,就不能指定任意的列,否则会报错。
3、shell操作
4、Java API
扫描表中的所有行的最新版本数据
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:itable");
Scan s = new Scan();
ResultScanner rs = table.getScanner(s);
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell))+ " Time : " + cell.getTimestamp());
}
table.close();
扫描指定行键范围,通过末尾加0,使得结果集包含StopRow
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:itable");
Scan s = new Scan();
s.setStartRow(Bytes.toBytes("100001"));
s.setStopRow(Bytes.toBytes("1000020"));
ResultScanner rs = table.getScanner(s);
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell))+ " Time : " + cell.getTimestamp());
}
table.close();
返回所有已经被打上删除标记但尚未被真正删除的数据
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:itable");
Scan s = new Scan();
s.setStartRow(Bytes.toBytes("100003"));
s.setRaw(true);
s.setMaxVersions();
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell))+ " Time : " + cell.getTimestamp());
}
table.close();
结合过滤器,获取所有age在25到30之间的行
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:itable");
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
SingleColumnValueFilter filter1 = new SingleColumnValueFilter(
Bytes.toBytes("info"), Bytes.toBytes("age"), CompareOp.GREATER_OR_EQUAL, Bytes.toBytes("25") );
SingleColumnValueFilter filter2 = new SingleColumnValueFilter(
Bytes.toBytes("info"), Bytes.toBytes("age"), CompareOp.LESS_OR_EQUAL, Bytes.toBytes("30") );
filterList.addFilter(filter1);
filterList.addFilter(filter2);
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner rs = table.getScanner(scan);
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : " +Bytes.toString(r.getRow()) + "Familiy:Quilifier : " + Bytes.toString(CellUtil.cloneQualifier(cell)) +
" Value : " + Bytes.toString(CellUtil.cloneValue(cell))+ " Time : " + cell.getTimestamp());
}
table.close();
注意:
- HBase对列族、列名大小写敏感