删除方法
删除方法如下:
void delete(Delete delete) throws IOException
在删除的时候需要一个Delete实例,构造函数如下:
Delete(byte[] row)
Delete(byte[] row, long timestamp, RowLock rowLock)
如果要多次频繁的修改同一行,还可以提供RowLock实例,指定自己的RowLock。
再删除的时候最好缩小要删除的给定行里涉及数据的范围:
Delete deleteFamily(byte[] family)
Delete deleteFamily(byte[] family, long tamestamp)
Delete deleteColumns(byte[] family, byte[] qualifier)
Delete deleteColumns(byte[] family, byte[] qualifier, long timestamp)
Delete deleteColumn(byte[] family, byte[] qualifier)
Delete deleteColumn(byte[] family, byte[] qualifier, long timestamp)
void setTimestamp(long timestamp)
deleteColumns()作用于特定的一列,如果没指定时间戳,这个方法会删除该列的所有版本,如果指定了时间戳,会删除所有与这个时间戳相匹配的版本或者更旧的版本。
deleteColumn()也作用于特定的一个列,但是只删除最新的版本或者指定的版本。
delete的列表
delete()列表的调用和put()列表的调用很类似,需要包含一个Delete实例的列表:
void delete(List<Delete> deletes) throws IOException
原子性操作 compare-and-delete
和前文类似,如果指定行键、列族、列限定符和值来执行删除操作的检查,如果检查失败就不执行删除操作,返回false,如果检查成功,则执行删除操作,返回true:
boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete) throws IOException
批处理操作
之前的操作都是基于单个实例或者列表来实现,这里的批处理调用可以批量处理跨多行的不同操作。
提供了batch()方法进行所有操作:
void batch(List<Row> actions, Object[] results)
throws IOException, InterriptedException
Object[] batch(List<Row> actions)
throws IOException, InterriptedException
Row类是Put、Get、Delete的父类
使用批处理的例子:
private final static byte[] ROW1 = Bytes.toBytes("row1");
private final static byte[] ROW2 = Bytes.toBytes("row2");
private final static byte[] COLFAM1= Bytes.toBytes("colfam1");
private final static byte[] COLFAM2= Bytes.toBytes("colfam2");
private final static byte[] QUAL1= Bytes.toBytes("qual1");
private final static byte[] QUAL2= Bytes.toBytes("qual2");
List<Row> batch = new ArrayList<Row>();
Put put = new put(ROW2);
put.add(COLFAM2, QUAL1, Bytes.toBytes("val5"));
batch.add(put);
Get get1 = new Get(ROW1);
get1.addColum(COLFAM1,QUAK1);
batch.add(get1);
Delete delete = new Delete(ROW1);
delete.deleteColumns(COLFAM1, QUAL2);
batch.add(delete);
Get get2 = new Get(ROW2);
get2.addColum(Bytes.toBytes("BOGUS"));
batch.add(get1)
Object results = new Object[batch.size()];
try{table.batch(batch,resluts);
}catch(Exception e){
System.out.println("Error: " + e);
}
for(int i=0;i<result.length;i++){
System.out.println("Result[" + i + "]:" + resluts[i]);
}
行锁
行锁保证只有一个客户端能获取一行数据相应的锁,同时对这行进行修改,一般尽可能的避免使用它,避免产生死锁的情况。
RowLock lockRow(byte[] row) throws IOException
void unlockRow(RowLock rl) throws IOException
扫描
扫描类似数据库中的游标。
Scan
扫描提供的类是Scan,但是不需要调用scan()方法创建实例,可以通过调用HTable的getScanner()方法返回扫描器,同时也可以用它迭代获得数据:
ResultScanner getScanner(Scan scan) throws IOException
ReslutScanner getScanner(byte[] family) throws IOException
ReslutScanner getScanner(byte[] family, byte[] qualifier) throws IOException
后两个方法隐式的帮用户创建了一个Scan实例,逻辑中最后调用getScanner(Scan scan)方法。
在创建Scan 实例后可以有多种方法限制扫描范围,例如
Scan addFamily(byte[] family)
Scan addColumn(byte[] family, byte[] qualifier)
...
ResultScanner
扫描的操作不会通过一次RPC请求就返回所有匹配的行,而是以行为单位进行返回。因为一次请求可能需要返回很多行,再一次请求中发送这么多数据会占用大量的系统资源并且花费很长时间。
ResultScanner吧扫描转换为类似get的操作,吧每一行封装成Result实例,吧所有Result实例放入一个迭代器:
Result next() throws IOException
Result[] next(int nbRows) throws IOexception
void close()
最好把close()方法放入try/finally中,因为一个打开的扫描器会占用不少服务器资源。
缓存与批量处理
前面的每一个next()的调用都会为每行数据生成一个单独的RPC请求,当单元格数据较小的时候,这样做的性能不是很好,如果此时一次可以获得更多行的数据会更好。有一个扫描器缓存可以实现,默认情况下这个缓存是关闭的。
可以使用HTable的方法设置表级的扫描器缓存:
void setScannerCaching(int scannerCaching)
int getScannerCaching()
也可以把下面的配置项添加到hbase-site.xml中
<property>
<name>hbase.client.scanner.caching</name>
<value>10</value>
</property>
这样所有的Scan实例的扫描器缓存的大小都为10.
还有扫描层面的配置,这层优先级最高,使用Scan类的方法设置扫描级的缓存:
void setCaching(int caching)
int getCaching()
很多时候,吧扫描器缓存设的比较高可以提高扫描性能,但是设置过高会使得每次next()调用占用更多时间,如果返回客户端数据超出堆的大小就会出现OutOfMemoryException异常。
如果数据量非常大的行,这些行有可能超过客户端进程的内存容量,这时候可以使用批量:
void setBatch(int batch)
int getBatch()
缓存是面向行的操作,批量是面向列一级的操作。批量可以选择每一次ResultScanner的实例的next()操作取回多少列。