hbase中sum结果为NULL的问题:AggregationClient执行聚合sum时,给scan添加列过滤器后,sum结果为 null

 

1. 情况说明

在使用hbase-endpoint依赖中的AggregationClient类,对hbase执行sum操作时,当scan不设置 filter时可以正常得到 sum的结果,但是设置filter之后,sum的结果就为 null。

1.1 不设置filter时的执行结果

不设置filter时的代码如下:

        String tableName = "hbaseTableName";
        String cf = "f";
        String col_ORG_ID = "ORG_ID";  // 在hbase列名是 ORG_ID
        Scan scan = new Scan();

        scan.addFamily(cf.getBytes());
        scan.addColumn(cf.getBytes(), col_ORG_ID.getBytes());
        AggregationClient ac = new AggregationClient(config.getHbaseConfiguration());
        DoubleColumnInterpreter columnInterpreter = new DoubleColumnInterpreter();
        Double sum = ac.sum(TableName.valueOf(tableName), columnInterpreter, scan);
        log.info("sum result [{}]", sum);

上述代码会对hbase表里的ORG_ID进行求sum操作。执行sum的结果是

sum result [18.8]

可以对某列执行求sum操作。

1.2 设置filter后执行结果为 null

这是filter的代码如下:

        String tableName = "hbaseTableName";
        String cf = "f";
        String col_ORG_ID = "ORG_ID";  // 在hbase列名是 ORG_ID
        Scan scan = new Scan();

        // 为scan设置filterList
        List<Filter> filters = new ArrayList<>();
        SingleColumnValueFilter scvf = new SingleColumnValueFilter(Bytes.toBytes(cf), Bytes.toBytes(col_ORG_ID), CompareOperator.EQUAL, Bytes.toBytes("100.05"));
        filters.add(scvf);
        scvf.setFilterIfMissing(true);
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL,filters);
        scan.setFilter(filterList);

        //对列进行求sum操作
        scan.addFamily(cf.getBytes());
        scan.addColumn(cf.getBytes(), col_ORG_ID.getBytes());
        AggregationClient ac = new AggregationClient(config.getHbaseConfiguration());
        DoubleColumnInterpreter columnInterpreter = new DoubleColumnInterpreter();
        Double sum = ac.sum(TableName.valueOf(tableName), columnInterpreter, scan);
        log.info("sum result [{}]", sum);

此时输出结果是: sum result [null]

为什么添加Filter后,再执行sum的结果就为null了呢。

2. 问题分析

为什么添加Filter后,再执行sum的结果就为null了呢。

经过分析,在SingleColumnValueFilter和Filter一起使用时,创建一个SingleColumnValueFilter对象,就需要在scan添加上这一列,加上如下代码就好了,因为 只有当COLUMNS中包含SingleColumnValueFilter提到的字段时, 该SingleColumnValueFilter才有效的 。(参考这篇文章的讲解):

scan.addColumn(cf.getBytes(), col_ORG_ID.getBytes());

2.2 注意事项

在创建SingleColumnValueFilter对象时,需要注意设置列的值时,注意区分数值型(Double)和字符串类型(String)的区别。

如果为这一列的值是String类型,使用下面的赋值方式:

new SingleColumnValueFilter(Bytes.toBytes(cf), Bytes.toBytes("TRX_DISC_AT" ), CompareOperator.EQUAL, Bytes.toBytes("50.3"));

如果这一列的值类型是Double,则需要使用下面的创建方法:

要将列值转化为对应的数值类型,例如Double类型:Double.valueOf("50.3")

new SingleColumnValueFilter(Bytes.toBytes(cf), Bytes.toBytes("TRX_DISC_AT" ), CompareOperator.EQUAL, Bytes.toBytes(Double.valueOf("50.3")));

 

这里还有一个坑,就是要添加的SingleColumnValueFilter列(例如column_02)如果是数值型,则在最终的计算结果中,也会将这一列也统计进去,即最后的结果是sum(column_01) + sum(column_02)。这时候就需要将最终的计算结果再减去这一列sum(column_02)的值。

如果在求sum时,不想统计sum(过滤列),则可以使用 SingleColumnValueExcludeFilter ,因为SingleColumnValueExcludeFilter会将该字段排除,仅仅用于过滤使用。

 

还是要多了解下hbase中的数据类型,例如string和数值型double的使用区别的

3. 结论

3.1 SingleColumnValueFilter列添加到scan对象中

使用SingleColumnValueFilter时,只有当scan的COLUMNS中包含SingleColumnValueFilter提到的字段时, 该SingleColumnValueFilter才有效的。[参考这里 => SingleColumnValueFilter should be able to find the column value even when it's not specifically added as input on the scan.]

即把col这一列添加到scan对象中去

//为scan添加列
scan.addColumn(cf.getBytes(), col.getBytes());

3.2 使用替代的SingleColumnValueExcludeFilter类

使用SingleColumnValueExcludeFilter这时只会返回除开AREA_ID和TIME_ID的字段, 但记录数是对的。这样就不用再手动把过滤列添加到scan对象了

 

3.3 的区别

请参考这一篇文章 SingleColumnValueFilter 和 SingleColumnValueExcludeFilter的区别

 

 

4. 参考链接

https://blog.csdn.net/zhangjianying/article/details/8628249  (重点参考下这篇,分析的比较详细)

http://www.bubuko.com/infodetail-542553.html

https://issues.apache.org/jira/browse/HBASE-2198

https://issues.apache.org/jira/browse/HBASE-2211

http://www.bubuko.com/infodetail-542553.html

https://bbs.csdn.net/topics/390223353

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
HBase的Scan操作默认情况下是按照行键升序排的,如果您想要将结果倒序排,可以使用ReverseFilter来实现。 ReverseFilter是一个HBase过滤器(Filter)类型,它可以反转Scan操作的结果顺序。以下是一个示例代码片段,演示如何在Scan操作使用ReverseFilter来实现结果倒序排: ``` import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.filter.FilterList; import org.apache.hadoop.hbase.filter.ReverseFilter; import org.apache.hadoop.hbase.util.Bytes; ... Table table = connection.getTable(TableName.valueOf("mytable")); Scan scan = new Scan(); scan.setReversed(true); FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); filterList.addFilter(new ReverseFilter()); scan.setFilter(filterList); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { // process results } scanner.close(); table.close(); ``` 在此示例,我们首先创建了一个名为“mytable”的表,并设置了一个Scan操作。然后,我们创建了一个FilterList对象,并向其添加了一个ReverseFilter对象,以实现结果倒序排。最后,我们使用Table对象的getScanner方法来获取一个ResultScanner对象,并遍历ResultScanner对象来处理扫描结果。 需要注意的是,在上面的示例代码,我们在Scan对象使用了setReversed(true)方法来启用倒序扫描。同,我们还将ReverseFilter对象添加到了FilterList对象。由于FilterList对象过滤器(Filter)将按照添加的顺序逐一作用于结果集,因此必须将ReverseFilter添加FilterList的最前面,以确保结果顺序正确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值