我们可以从HBase表中获取所有列名吗?

时间:2015-10-19 23:56:54

标签: hadoop hbase

设定:

我有一个HBase表,有100M +行和1百万+列。每行只有2到5列的数据。只有一个列族。

问题:

我想找出此qualifiers中所有不同的column family(列)。有快速的方法吗?

我可以考虑扫描整个表格,然后获取每行familyMap,获取qualifier并将其添加到Set<>。但这将非常缓慢,因为有100M +行。

我们可以做得更好吗?

3 个答案:

答案 0 :(得分:2)

您可以使用mapreduce。在这种情况下,您不需要为协处理器安装hbase的自定义库。 下面是用于创建mapreduce任务的代码。

作业设置

    Job job = Job.getInstance(config);
    job.setJobName("Distinct columns");

    Scan scan = new Scan();
    scan.setBatch(500);
    scan.addFamily(YOU_COLUMN_FAMILY_NAME);
    scan.setFilter(new KeyOnlyFilter()); //scan only key part of KeyValue (raw, column family, column)
    scan.setCacheBlocks(false);  // don't set to true for MR jobs


    TableMapReduceUtil.initTableMapperJob(
            YOU_TABLE_NAME,
            scan,          
            OnlyColumnNameMapper.class,   // mapper
            Text.class,             // mapper output key
            Text.class,             // mapper output value
            job);

    job.setNumReduceTasks(1);
    job.setReducerClass(OnlyColumnNameReducer.class);
    job.setReducerClass(OnlyColumnNameReducer.class);

映射

 public class OnlyColumnNameMapper extends TableMapper<Text, Text> {
    @Override
    protected void map(ImmutableBytesWritable key, Result value, final Context context) throws IOException, InterruptedException {
       CellScanner cellScanner = value.cellScanner();
       while (cellScanner.advance()) {

          Cell cell = cellScanner.current();
          byte[] q = Bytes.copy(cell.getQualifierArray(),
                                cell.getQualifierOffset(),
                                cell.getQualifierLength());

          context.write(new Text(q),new Text());  

       }
 }

}

减速

public class OnlyColumnNameReducer extends Reducer<Text, Text, Text, Text> {

    @Override
    protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {    
            context.write(new Text(key), new Text());    
    }
}

答案 1 :(得分:1)

HBase可以显示为分布式NavigableMap<byte[], NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>>

没有“元数据”(比如集中存储在主节点中的内容)关于所有区域服务器中可用的所有限定符的列表。

因此,如果您有一次性使用案例,那么唯一的方法就是扫描整个表并在Set<>中添加限定符名称,就像您提到的那样。

如果这是重复用例(如果您有权将组件添加到技术堆栈中),您可能需要考虑添加Redis。可以使用Redis Set以分布式方式维护一组限定符。

答案 2 :(得分:0)

HBase协处理器可用于此方案。您可以编写自定义EndPoint实现,其工作方式类似于RDBMS中的存储过程。它在服务器端执行您的代码,并为每个区域获取不同的列。在客户端,您可以获得所有区域的不同列。

效果优势:所有列都不会传输到客户端,从而减少了网络通话次数。