为什么说HBase的行是按词法排序存储的?

问题描述 投票:1回答:1

基于HBase的 文件,同样是按照Google BigTable论文中的参考资料,说是用行键的词法排序来存储行。

很明显,当我们在行键中有一个字符串,或者我们将一个字符串转换为字节数组并存储时,行是以词法排序的。事实上,对于这个问题。即使你把一个整数转换成字符串,然后再转换成字节数组,也是有意义的。例如 下面的hbase shell把数字转换成字符串,然后存储起来

create 'test', 'cf'
put 'test', '1', 'cf:c1', 'xyz1'
put 'test', '2', 'cf:c1', 'xyz2'
put 'test', '11', 'cf:c1', 'xyz11'

scan 'test3'
ROW                                         COLUMN+CELL
 1                                          column=cf:c1, timestamp=1589736288540, value=xyz1
 11                                         column=cf:c1, timestamp=1589736311607, value=xyz11
 2                                          column=cf:c1, timestamp=1589736301167, value=xyz2
3 row(s) in 0.0080 seconds

另一方面,我可以使用HBase客户端实用程序,以编程的方式将数字转换为字节数组(org.apache.hadoop.hbase.util.Bytes,其中使用了Big Endian stuffs......),我看到行是自然排序的,而不是用词法排序。对于上面类似的数据和表格,我用下面的代码把数据放到HBase表中。

val put = new Put(Bytes.toBytes(11L))
put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("c1"), Bytes.toBytes("abc"))
table.put(put)

扫描结果是

hbase(main):014:0> scan 'test2'
ROW                                        COLUMN+CELL
 \x01                                      column=cf:a, timestamp=1589727058289, value=abc \\1
 \x02                                      column=cf:a, timestamp=1589727099714, value=abc \\2
 \x0B                                      column=cf:a, timestamp=1589727147449, value=abc \\11
 {                                         column=cf:a, timestamp=1589733907127, value=abc \\123
 \xF8                                      column=cf:a, timestamp=1589733854179, value=abc \\112312312L
5 row(s) in 0.0080 seconds

我的问题是--由整数生成的字节数组的词法排序与自然排序相同,这是否纯属巧合? 我们将长数组转换为字节数组的方式,实际上是用一些值来填充,以获得有效的自然排序? 如果不是,为了处理非类型的行键,是不是说行键是按词法排序的,这样与字符串等数据类型混排时,排序就有了预定的顺序?在后一种情况下,在我看来,并不是说行键是严格按照词法排序的,因为只是为了满足我们对非类型列(这里的行键)的需求,所以才会这样构建。

基本上,就是这里的字节编码-&gt.toBytes(long)。Bytes.toBytes(long) 保序 Long? 即是说,词法上的排序会不会有 Array[Byte] 函数返回的内容与自然排序的内容相同。Long 被当作输入?

hbase bigtable lexicographic row-key
1个回答
3
投票

你这个问题的答案是肯定的。但如果你混合使用不同大小的键,就要小心了。比如说,如果你使用所有大小相同的键,并且都是用 Bytes.toBytes(long)它们将保持自然的长顺序。如果你混合了不同大小的字节数组,情况就不是这样了,因为,正如你所展示的,一个字节 "1 "将围绕着两个字节 "11",例如。

在这样的情况下 toBytes(),它使用的是固定长度的大恩迪安编码。比如说你用四个字节,那么排序就会像。

00 00 00 00 (long value 0)
00 00 00 01 (long value 1)
00 00 00 02
...
00 00 01 00 (long value 256)
...

这将使自然数和密钥世代的排序相同。

© www.soinside.com 2019 - 2024. All rights reserved.