【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\[email protected]\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: "[email protected]"

根据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

细心的话可以发现输出的几个也是按照降序的顺序排列的

时间: 2024-08-14 08:10:41

【hbase】——bulk load导入数据时value=\x00\x00\x00\x01问题解析的相关文章

DB2导入数据时乱码问题

1.由于导入import导入数据时乱码,一直找不到解决办法,于是就用load导入 LOAD后,发现某些表检查挂起( 原因码为 "1",所以不允许操作 SQLSTATE=57016 ) 解决办法:set integrity for xxxxxx immediate checked 2.表锁定(原因码为7) 解决办法:reorg table xxxx 3.去重 select distinct a.column from table1 as a inner join table2 as b

MYSQL导入数据时,出现错误:Incorrect string value: &#39;\xF0\x9F...&#39; for column &#39;XXX&#39; at row 1

Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1 这个问题,原因是UTF-8编码有可能是两个.三个.四个字节.Emoji表情或者某些特殊字符是4个字节,而MySQL的utf8编码最多3个字节,所以数据插不进去. 我的解决方案是这样的 1.在mysql的安装目录下找到my.ini,作如下修改: [mysqld] character-set-server=utf8mb4 [mysql] default-character-

SQL Server导入数据时“启用标示插入”详解

在SQL Server中导入数据时,会有一个"启用标示插入"的选项,突然间懵逼了,这到底啥意思?我选与不选这个选项,结果好像没区别!不科学啊这,"存在即合理",我相信这个选项肯定有它的用处,只是我不知道罢了. 于是我去查资料,在CSDN论坛里找到了可能的解释: 1)首先:"启用标示插入"只对标示列(identity定义的列)起作用.所以如果你要使用这个功能,肯定得有标示列了.我当时狂晕的地方在于,我没在数据库创建表,而是直接在导入数据的过程中创建

Navicat导入数据时发生了报错 --- 1153 - Got a packet bigger than &#39;max_allowed的处理办法

今天我在使用Navicat导入.sql文件数据时,发现本来是80万条的数据,结果只导入了10万条左右,而且在其错误信息日志中,我发现了这样一条错误:1153 - Got a packet bigger than 'max_allowed. 度娘了一番后,发现越来是我的SQL文件远远大于MySQL默认执行的文件大小,所以执行不过去. 解决方法: 在MySQL安装目录下找到文件my.ini,搜索[mysqld],在其下面添加一句话 max_allowed_packet=521M  ##该处按照自己的

并发拉取HBase大量指定列数据时卡住的问题排查

最近遇到一例,并发拉取HBase大量指定列数据时,导致应用不响应的情形.记录一下. 背景 退款导出中,为了获取商品规格编码,需要从HBase表 T 里拉取对应的数据. T 对商品数据的存储采用了 表名:字段名:id 的列存储方式.由于这个表很大,且为详情公用,因此不方便使用 scan 的方式,担心带来集群的不稳定,进而影响详情和导出的整体稳定性. 要用 multiGet 的方式来获取多个订单的这个列的数据. 就必须动态生成相应的列,然后在 HBase 获取数据的时候指定列集合. 现有记录集合 L

(转)SSIS处理导入数据时, 存在的更新, 不存在的插入

问题描述: 当你把数据从其他数据库, 或者是文本文件之类的其他数据源导入到目的数据库时, 有时希望在导入的处理中, 能够实现"数据存在时更新, 不存在时导入" 在之前, 一般是通过导入临时表, 然后再判断处理导入正式表的, 在SQL Server 2005中, SSIS可以在导入处理时直接完成这种处理. 下面具体演示一下如何用SSIS完成这样的处理: 1.          准备测试环境 -- 1. 在数据库中创建下面的对象 USE tempdb GO CREATE TABLE dbo

Elasticsearch —— bulk批量导入数据

bulk批量导入 批量导入可以合并多个操作,比如index,delete,update,create等等.也可以帮助从一个索引导入到另一个索引. 语法大致如下: action_and_meta_data\n optional_source\n action_and_meta_data\n optional_source\n .... action_and_meta_data\n optional_source\n 需要注意的是,每一条数据都由两行构成(delete除外),其他的命令比如index

asp.net线程批量导入数据时通过ajax获取执行状态

最近因为工作中遇到一个需求,需要做了一个批量导入功能,但长时间运行没个反馈状态,很容易让人看了心急,产生各种臆想!为了解决心里障碍,写了这么个功能. 通过线程执行导入,并把正在执行的状态存入session,既共享执行状态,通过ajax调用session里的执行状态,从而实现反馈导入状态的功能! 上代码: 前端页面 <!DOCTYPE html> <html lang="en"> <head>  <meta charset="UTF-8

解决导入数据时提示分区数据不能导入问题

oracle导入数据的时候,有时会出现分区数据不能导入的问题,以及在迁移表空间的时候可能存在的索引状态为'UNUSABLE'的隐患,下面为解决方案: --查询出所有的状态为UNUSABLE的索引,并生成出来SQL select   'alter index ' ||  index_name || ' rebuild ;' from user_indexes where status='UNUSABLE';--例子: alter index PK_UN_ORGANIZATION_FUNCTION