【问题标题】:HBase: How does HBase know if a row contains a particular columnHBase:HBase 如何知道一行是否包含特定列
【发布时间】:2015-09-13 20:50:31
【问题描述】:

HBase 如何知道一行是否包含特定列?例如考虑以下情况:

假设我们有一个表,其中包含一个名为“STAT_FAM”的列族,包含以下两行:

  • 一行,键为“R1”,包含 1000 个名为 S1 到 S1000 的列。
  • 还有一个键为“R2”的行,其中包含另外 1000 个从 S2000 到 S3000 的列。

现在,如果我们正在扫描表,并且扫描定义如下:

Scan s = new Scan();
s.setStartRow ( Bytes.toBytes(“R1”) );
s.setStopRow ( Bytes.toBytes(“R2”) );
s.addColumn( STAT_FAM, Bytes.toBytes(“S500”) );
s.addColumn( STAT_FAM, Bytes.toBytes(“S2500”) );

当 HBase 进行扫描时,基于 rowkey,它会在特定区域服务器上的特定文件中定位记录。一旦定位,它如何找到行数据中的特定列?

对于“R1”行,没有名为“S2500”的列,是否必须通过该行的完整记录才能确定该行不包含所需的列?

提前致谢!

【问题讨论】:

    标签: hbase


    【解决方案1】:

    让我们首先了解 HBase 是如何存储它的数据的。

    Hfile的KeyValue包括:

    <keylength> <valuelength> <key> <value>
    

    密钥分解为:

    <rowlength> <row> <columnfamilylength> <columnfamily> <columnqualifier> <timestamp> <keytype>
    

    一起来

    <keylength> <valuelength> <key> <rowlength> <row> <columnfamilylength> <columnfamily> <columnqualifier> <timestamp> <keytype> <value>
    

    HBase 是“面向列族的”。数据以物理方式存储在列族组中。这意味着给定列族的所有键值都存储在同一组文件中。

    HBase 不提供任意列的索引,不提供连接,也不提供多行事务。如果你想根据它的列值查询一行,你最好为此维护一个二级索引,或者为全表扫描做好准备

    较新版本的 Hbase HFile 具有内存高效的文件格式。但不保证查找所有行。

    检查每一行的证明都在这里。

    类名:org.apache.hadoop.hbase.filter.SingleColumnValueFilter

    if (!keyValue.matchingColumn(this.columnFamily, this.columnQualifier)) {
          return ReturnCode.INCLUDE;
        }
    
    if (filterColumnValue(keyValue.getBuffer(), keyValue.getValueOffset(), keyValue.getValueLength())) {
          return this.latestVersionOnly? ReturnCode.NEXT_ROW: ReturnCode.INCLUDE;
    }
    

    以及来自 org.apache.hadoop.hbase.KeyValue 类的这个方法。

      /**
       *
       * @param family column family
       * @param qualifier column qualifier
       * @return True if column matches
       */
      public boolean matchingColumn(final byte[] family, final byte[] qualifier) {
        int rl = getRowLength();
        int o = getFamilyOffset(rl);
        int fl = getFamilyLength(o);
        int ql = getQualifierLength(rl,fl);
        if (!Bytes.equals(family, 0, family.length, this.bytes, o, fl)) {
          return false;
        }
        if (qualifier == null || qualifier.length == 0) {
          if (ql == 0) {
            return true;
          }
          return false;
        }
        return Bytes.equals(qualifier, 0, qualifier.length,
            this.bytes, o + fl, ql);
      }
    
    
    Image credit: Cloudera-blog
    

    【讨论】:

    • 感谢您的解释。你也可以在这里发布源链接吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多