我们都知道 HBase 的数据根据 rowkey 字典序排序的,理解这个概念很重要。
先理解名词 - 「字典序」
根据 wiki 解释:
在英文字典中,排列单词的顺序是先按照第一个字母以升序排列(即a、b、c……z 的顺序);如果第一个字母一样,那么比较第二个、第三个乃至后面的字母。如果比到最后两个单词不一样长(比如,sigh 和 sight),那么把短者排在前。
通俗的理解,字典序是把字符左对齐,从左到右比大小的排序,一旦比出大小就停止比较后续的字符。
那么排序规则是什么?如果只考虑字母的话,就是: a < b < c < ... < z,当然这个规则也是人为约定的,举例以下就是字典序:
a
ab
abc
b
理解 HBase Rowkey 的字典序
有了之前的概念,理解 HBase Rowkey 字典序会容易一点:
- rowkey 字符串左对齐,从左到右比大小,比到就停止
- 怎么比大小:基于字符的 ASCII 码大小 ,例如ASCII 中 A < a,a < b , 1 < 2, 1 < a 具体可以参考 wiki。
下面这里从实现层面举个例子:假如 HBase 要比较 rowkey "19" 和 "2" ,怎么做?
- 将 rowkey 转为字节数组, “19” => [49,57] ,"2" => [50]
- 从两个字节数组下标 0 开始往后比大小
- 第一个字节 50 比 49 大,所以排序是 2 > 19
byte[] a = "19".getBytes()
// => [49,57]
byte[] b = "2".getBytes()
// => [50]
这里值得一提的是:ASCII 可见字符都是单字节表示,所以字符与 ASCII 字节数组是一一对应的。
但如果你用非 ASCII 可见字符做 rowkey ,例如汉字,就会出现不可控因素,因为一个汉字对应的是多个字节。所以建议 rowkey 就采用常见的可见字符,避免用特殊字符。
ASCII 码可显示字符有 95 个,大致顺序如下
! “ #$... 0123..9..ABC..Z...abc...z..~
第一个是:「空格」,最后一个是:「~」
下一篇将讲讲 rowkey 的设计与优化,包括预分区的选择策略。