HBase批量删除为"完成批量加载"

时间:2016-09-02 12:56:43

标签: hbase

我想在HBase表中删除3亿个行。我可以使用HBase API并发送一批Delete对象。但我担心需要很多时间。

以前的代码是我要插入数百万行的情况。我没有使用HBase API并发送批量Puts,而是使用了Map Reduce作业,它将RowKey / Put作为值发出,并使用HFileOutputFormat2.configureIncrementalLoad(job, table, regionLocator)设置我的Reducer,以便它直接写入准备快速加载的输出LoadIncrementalHFiles(完整批量加载)。它要快得多(5分钟而不是3小时)。

所以我想对批量删除做同样的事情。

但是,似乎我不能将此技术用于删除HFileOutputFormat2尝试为KeyValuePut(PutSortReducer)配置Reducer,但删除不存在任何内容。

我的第一个问题是为什么没有" DeleteSortReducer"为Delete启用完整的批量加载技术?它只是缺少的东西,还没有完成?或者有更深层次的理由证明这一点吗?

第二个问题,这是一种相关的问题:如果我复制/粘贴PutSortReducer的代码,将其修改为删除并将其作为我的工作的减速器传递,它会起作用吗? 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);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:4)

首先,简单介绍一下删除操作在HBase中是如何工作的。在删除命令中,HBase将数据标记为已删除,并将有关它的信息写入HFile。实际上,数据不会从光盘中删除,并且存储中存在两条记录:数据和删除标记。只有在压缩之后,才会从光盘存储中删除数据。

所有这些信息都表示为KeyValue。对于代表数据的KeyValue,KeyValue.Type等于Put。对于删除标记,KeyValue.Type设置为以下值之一DeleteDeleteColumnDeleteFamilyDeleteFamilyVersion

在您的情况下,您可以通过为KeyValue.Type创建具有特殊值的KeyValue来实现批量删除。例如,如果要删除唯一的一列,则应使用构造函数

创建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)

对于您不需要特殊DeleteSortReducer的第一个问题的答案,您应该为KeyValue配置缩减器。第二个问题的答案是否定的。

相关问题