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

Posted

技术标签:

【中文标题】我们可以从 HBase 表中获取所有列名吗?【英文标题】:Can we get all the column names from an HBase table? 【发布时间】:2015-10-19 23:56:53 【问题描述】:

设置:

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

问题:

我想找出这个column family 中所有不同的qualifiers(列)。有没有快速的方法来做到这一点?

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

我们还能做得更好吗?

【问题讨论】:

【参考方案1】:

您可以为此使用 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());    
    

【讨论】:

【参考方案2】:

HBase 可以可视化为分布式NavigableMap&lt;byte[], NavigableMap&lt;byte[], NavigableMap&lt;byte[], NavigableMap&lt;Long, byte[]&gt;&gt;&gt;&gt;

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

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

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

【讨论】:

【参考方案3】:

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

性能优势:所有列都不会传输到客户端,从而导致网络调用减少。

【讨论】:

以上是关于我们可以从 HBase 表中获取所有列名吗?的主要内容,如果未能解决你的问题,请参考以下文章

您可以从 SqlDataReader 获取列名吗?

按键从 HBase 表中获取值

如何从laravel中的表中选择所有列名?

如何从 SQL Server 中特定数据库的表中获取所有列名?

了解 HBase Java 客户端

只需从配置单元表中获取列名