【hbase】——bulkload导入数据时value=x00x00x00x01问题解析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【hbase】——bulkload导⼊数据时value=x00x00x00x01问题解
析
⼀、存⼊数据类型
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();
}
ng.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
细⼼的话可以发现输出的⼏个也是按照降序的顺序排列的。