【hbase】——bulk load導入數據時value=\x00\x00\x00\x01問題解析


一、存入數據類型

Hbase里面,rowkey是按照字典序進行排序。存儲的value值,當用filter進行數據篩選的時候,所用的比較算法也是字典序的。

1、當存儲的value值是float類型的時候,錄入數據可以錄入,但是讀取出來的數據會存在問題會出問題

例如:

存入數據的代碼:

p = new Put(Bytes.toBytes(“66”));

p.add(Bytes.toBytes("value"),Bytes.toBytes("null"), (Long.valueOf(“668”) ), Bytes.toBytes(Float.valueOf(533.0)));

...

在hbase shell里面取出的數據:

hbase(main):007:0> get 'DATA‘, '66'
COLUMN                CELL
value:null           timestamp=668, value=D\x05@\x00
1 row(s) in 0.1100 seconds
可以看到取出來的value值是不可讀的。

在java程序里面則沒有返回結果,如果想強制類型轉換讀取這個數據,則會報錯,說格式錯誤:

  try {
   Result rr = table.get(g);
   for (KeyValue kvv : rr.raw()) {
float f = Float.parseFloat(new String(kvv.getValue()));
    System.out.println(f);
    tempList.add(kvv.getTimestamp() + "," + new String(kvv.getValue()));
   }
  } catch (IOException e) {
   e.printStackTrace();
  }

java.lang.NumberFormatException: For input string: "D@"

根據hbase都是按照字典序進行排序的前提,(字典序多少針對字符串的),可以推測hbase不支持float類型數據的存儲

2、如果把錄入數據改成int型

存入數據的代碼:

p = new Put(Bytes.toBytes(“66”));

p.add(Bytes.toBytes("value"),Bytes.toBytes("null"), (Long.valueOf(“668”) ), Bytes.toBytes(Integer.valueOf(533.0)));

...

取出的數據

hbase(main):007:0> get 'DATA‘, '66'

COLUMN CELL
value:null timestamp=668, value=\x00\x00\x00\x00\x00\x00\x02\x15
1 row(s) in 1.4510 seconds

在java程序里面則沒有返回結果,當試圖把取出的數據強制類型轉換的時候,同樣報錯

3、 如果把錄入數據改成long型

存入數據的代碼:

p = new Put(Bytes.toBytes(“66”));

p.add(Bytes.toBytes("value"),Bytes.toBytes("null"), (Long.valueOf(“668”) ), Bytes.toBytes(Long.valueOf(533.0)));

...

取出的數據

hbase(main):007:0> get 'DATA‘, '66'

COLUMN                CELL
value:null           timestamp=668, value=\x00\x00\x00\x00\x00\x00\x02\x15
1 row(s) in 1.4510 seconds

同樣不可讀

4、如果把錄入value格式改成String類型,則正常

存入數據的代碼:

p = new Put(Bytes.toBytes(“66”));

p.add(Bytes.toBytes("value"),Bytes.toBytes("null"), (Long.valueOf(“668”) ), Bytes.toBytes("533.0"));

...

取出的數據

hbase(main):007:0> get 'DATA‘, '66'

COLUMN                CELL
value:null           timestamp=668, value=533.0
1 row(s) in 0.8500 seconds

在java程序里面也有可用的結果

通過上述測試說明,hbase現在只支持String類型數據的存取

二、 小的注意點

1、取value的時候一定要用 new String(kv[i].getValue())的格式

    System.out.println(kv[i].getValue().toString());     錯誤
    System.out.println(new String(kv[i].getValue()));    正確

2、用完ResultScanner 后一定要記得關掉:resultScanner.close();

3、當錄入的數據已經使用了String類型

那么,進行比較的時候也要使用String類型。例如下面使用float類型的filter,則不會對結果產生任何影響

  Filter filter = new SingleColumnValueFilter(
             Bytes.toBytes("value"),Bytes.toBytes("null") , CompareOp.LESS,Bytes.toBytes(Float.valueOf((float) 5.0)));
  scan.setFilter(filter); 
如果換成

  Filter filter = new SingleColumnValueFilter(
             Bytes.toBytes("value"),Bytes.toBytes("null") , CompareOp.LESS,Bytes.toBytes("5.0"));

scan.setFilter(filter);

則會會結果產生影響,但是需要注意的是,這里的設置方式也是錯誤的

追蹤原因:

hbase關於比較的相關源碼如下:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 
  public static int compareTo(final byte [] left, final byte [] right) {
    return compareTo(left, 0, left.length, right, 0, right.length);
  }

 
  public static int compareTo(byte[] buffer1, int offset1, int length1,
      byte[] buffer2, int offset2, int length2) {
    // Bring WritableComparator code local
    int end1 = offset1 + length1;
    int end2 = offset2 + length2;
    for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
      int a = (buffer1[i] & 0xff);
      int b = (buffer2[j] & 0xff);

      if (a != b) {
        return a - b;
      }
    }
    return length1 - length2;
  }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

疑問:下面long型篩選,返回的結果並沒有value值,但是,結果的數據條數卻會發生變化,即使針對這個特定的時間戳讀取數據也沒有結果數據(曾試圖用scan確定了那個rowkey的那個列簇的那個列的那個時間戳,任何通過這些信息用get進行取值,但是也不能返回value值),為什么結果的條數會發生變化呢?

1、filter

(1)錄入的value是long型

如果想設置成數值型比較,則要進行數據類型設置,如下

Filter filter = new SingleColumnValueFilter(
             Bytes.toBytes("value"),Bytes.toBytes("null") , CompareOp.LESS,Bytes.toBytes(Long.valueOf(5)));
  scan.setFilter(filter);

resultScanner = table.getScanner(scan);

結果是:

rowkey                         列簇:列名 時間戳   value

115404869300388065  value:null     27

115404869300388065  value:null     26

但是如果設置成字符串行,如下:

Filter filter = new SingleColumnValueFilter(
Bytes.toBytes("value"),Bytes.toBytes("null") , CompareOp.LESS,Bytes.toBytes(”5“));
scan.setFilter(filter);

resultScanner = table.getScanner(scan);

則返回的是按照字典序比較的結果(ps:rowkey是按照字典序排列的,10000比2 “小”)

115404869300388065  value:null  27

115404869300388065  value:null  3

115404869300388065  value:null  2

115404869300388065  value:null  1

細心的話可以發現輸出的幾個也是按照降序的順序排列的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM