为什么说 HBase 行按字典顺序存储?
Why HBase rows are said to be stored as lexicographically sorted?
基于 HBase documentation,再次参考 Google BigTable 论文,据说这些行是按行键的字典顺序存储的。
很明显,当我们在rowkey中有一个字符串或者我们将一个字符串转换为字节数组并存储它时,这些行是按字典顺序排序的。事实上,即使您将整数转换为字符串,然后再转换为字节数组,这也是有意义的。
例如:下面的 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 东西......)以编程方式将数字转换为字节数组,我看到这些行是自然的排序,而不是按字典顺序排列。对于和上面table相似的数据,我用下面的代码把数据放到HBase Table.
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
我的问题是 -
从整数生成的字节数组的字典顺序与自然顺序相同 或 是否纯属巧合我们将 long 转换为字节数组的方式实际上是用一些值填充获得有效的自然排序?
如果不是,为了处理非类型行键,我们是说行键按字典顺序排序,以便在与字符串和其他数据类型混合匹配时,排序具有预定顺序?在后一种情况下,在我看来,行键严格按照字典顺序排序是不正确的,因为只是为了满足我们拥有非类型化列(这里是行键)的需要,它是这样构建的......!
基本上,这里的字节编码 -> Bytes.toBytes(long) 是否保留了 Long
的自然顺序?也就是说,函数returns的Array[Byte]
的字典序和作为输入的Long
的自然序是一样的吗?
你的问题的答案是肯定的。但是,如果您混合使用不同的密钥大小,请小心。例如,如果您使用相同大小的所有键,并且全部使用 Bytes.toBytes(long)
生成,它们将保持自然的长序。如果您混合使用不同大小的字节数组,情况就不会如此,因为如您所示,例如,一个字节“1”将围绕两个字节“11”。
在toBytes()
的情况下,它使用固定长度的big endian编码。假设您使用四个字节,那么排序将是这样的:
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)
...
这将在自然数和密钥生成中进行相同的排序。
基于 HBase documentation,再次参考 Google BigTable 论文,据说这些行是按行键的字典顺序存储的。
很明显,当我们在rowkey中有一个字符串或者我们将一个字符串转换为字节数组并存储它时,这些行是按字典顺序排序的。事实上,即使您将整数转换为字符串,然后再转换为字节数组,这也是有意义的。 例如:下面的 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 东西......)以编程方式将数字转换为字节数组,我看到这些行是自然的排序,而不是按字典顺序排列。对于和上面table相似的数据,我用下面的代码把数据放到HBase Table.
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
我的问题是 -
从整数生成的字节数组的字典顺序与自然顺序相同 或 是否纯属巧合我们将 long 转换为字节数组的方式实际上是用一些值填充获得有效的自然排序?
如果不是,为了处理非类型行键,我们是说行键按字典顺序排序,以便在与字符串和其他数据类型混合匹配时,排序具有预定顺序?在后一种情况下,在我看来,行键严格按照字典顺序排序是不正确的,因为只是为了满足我们拥有非类型化列(这里是行键)的需要,它是这样构建的......!
基本上,这里的字节编码 -> Bytes.toBytes(long) 是否保留了 Long
的自然顺序?也就是说,函数returns的Array[Byte]
的字典序和作为输入的Long
的自然序是一样的吗?
你的问题的答案是肯定的。但是,如果您混合使用不同的密钥大小,请小心。例如,如果您使用相同大小的所有键,并且全部使用 Bytes.toBytes(long)
生成,它们将保持自然的长序。如果您混合使用不同大小的字节数组,情况就不会如此,因为如您所示,例如,一个字节“1”将围绕两个字节“11”。
在toBytes()
的情况下,它使用固定长度的big endian编码。假设您使用四个字节,那么排序将是这样的:
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)
...
这将在自然数和密钥生成中进行相同的排序。