我想删除HBase表中的3亿行。我可以使用HBase API并发送一批Delete对象。但是恐怕要花很多时间。
以前的代码就是这种情况,我想插入数百万行。我没有使用HBase API并发送大量的Puts,而是使用Map Reduce作业,该作业发出RowKey / Put作为值,并使用HFileOutputFormat2.configureIncrementalLoad(job, table, regionLocator)来设置我的Reducer,以便它直接写输出准备快速加载LoadIncrementalHFiles(完整批量加载) 。这要快得多(5分钟而不是3小时)。
因此,我想对批量删除执行相同的操作。
但是,似乎无法将这种技术与Delete结合使用,因为它HFileOutputFormat2试图为KeyValue或Put(PutSortReducer)配置Reducer,但是Delete不存在。
我的第一个问题是,为什么没有“ DeleteSortReducer”来启用完整的批量删除技术?只是缺少的东西,还没有做到吗?还是有更深层的理由证明这一点?
第二个问题是相关的:如果我复制/粘贴PutSortReducer的代码,将其修改为Delete并将其作为我的工作的Reducer传递,它将起作用吗?HBase完整的批量加载是否会产生充满墓碑的HFile?
范例:
public class DeleteSortReducer extends
Reducer<ImmutableBytesWritable, Delete, ImmutableBytesWritable, KeyValue> {
@Override
protected void reduce(
ImmutableBytesWritable row,
java.lang.Iterable<Delete> deletes,
Reducer<ImmutableBytesWritable, Delete,
ImmutableBytesWritable, KeyValue>.Context context)
throws java.io.IOException, InterruptedException
{
// although reduce() is called per-row, handle pathological case
long threshold = context.getConfiguration().getLong(
"putsortreducer.row.threshold", 1L * (1<<30));
Iterator<Delete> iter = deletes.iterator();
while (iter.hasNext()) {
TreeSet<KeyValue> map = new TreeSet<KeyValue>(KeyValue.COMPARATOR);
long curSize = 0;
// stop at the end or the RAM threshold
while (iter.hasNext() && curSize < threshold) {
Delete d = iter.next();
for (List<Cell> cells: d.getFamilyCellMap().values()) {
for (Cell cell: cells) {
KeyValue kv = KeyValueUtil.ensureKeyValue(cell);
map.add(kv);
curSize += kv.heapSize();
}
}
}
context.setStatus("Read " + map.size() + " entries of " + map.getClass()
+ "(" + StringUtils.humanReadableInt(curSize) + ")");
int index = 0;
for (KeyValue kv : map) {
context.write(row, kv);
if (++index % 100 == 0)
context.setStatus("Wrote " + index);
}
// if we have more entries to process
if (iter.hasNext()) {
// force flush because we cannot guarantee intra-row sorted order
context.write(null, null);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先,简单介绍一下HBase中删除操作的工作方式。使用delete命令时,HBase将数据标记为已删除,并将有关该数据的信息写入HFile。实际上,数据不会从光盘中删除,并且存储中存在两条记录:数据和删除标记。只有压缩后,数据才会从光盘存储中删除。
所有这些信息都表示为KeyValue。对于KeyValue,代表的数据KeyValue.Type等于Put。对于删除标记KeyValue.Type是下列值的集合中的一个Delete,DeleteColumn,DeleteFamily,DeleteFamilyVersion。
您可以通过创建具有特殊值的KeyValue来实现批量删除KeyValue.Type。例如,如果您只想删除一列,则应KeyValue使用构造函数创建一个
KeyValue(byte[] row, byte[] family, byte[] qualifier, long timestamp, KeyValue.Type type)
// example
KeyValue kv = new KeyValue(row, family, qualifier, time, KeyValue.Type.DeleteColumn)
Run Code Online (Sandbox Code Playgroud)
您不需要特殊答案的第一个问题的答案DeleteSortReducer,您应该为KeyValue。对于第二个问题,答案是否定的。
| 归档时间: |
|
| 查看次数: |
1106 次 |
| 最近记录: |