HBase是按列存储设计的,这种设计对随机读有很好的优化提升。通过rowId作为标识会很快从HBase中获得一行的数据。
扫描一部分或整张表的数据的性能完全是另一回事。首先,它是有顺序的。这意味着它的查询将相当慢,因为它没有使所有的RegionServer
同时在进行查询。
它实现的方式是按Scan命令的约束来完成的——即返回的结果集是按key排好序的。
那怎么样才能提高其性能呢?
从HBase中获取数据的通常做法是使用其API,大多使用的是Scan即相关对象。为了能达到提高其查询性能的目的,将同样采用这些API。
通过指定startRow和stopRow,从而使每次Scan操作只遍历一部分key的数据区域。
这种方案最关键值得注意的是HBase中key的排序的特性。HBase是按key的升序的值来扫描表的数据。
既然key的类型都是字符串类型,key以“1”开头的小于以“2”开头的,
因为它们是按字典顺序进行的排序。因此,值为“12345”的key同样小于“2”。充分利用此特性,根据key的第一个字符的值使整个key的数据区域到达分区的目的。
在此示例中,key只包含数字。10个区域范围:
null-1
1-2
2-3
3-4
4-5
5-6
6-7
7-8
8-9
9-null
性能的提升来自于,每一个范围的查询都定位于自己的分区。事先将表进行预split操作,将表分成10个分区。10分区刚好与HBase集群的情况一致(作者的集群
RegionServer数目大于10).因此每个分区将会在不同的RegionServer上。这样就会使Scan的请求操作并行执行——这将确切的提高整个操作的性能。
表是通过以下方式创建的:
$ create 'tariff_changes', { NAME => 'cf', SPLITS_FILE => 'splits.txt', VERSIONS => 50, MAX_FILESIZE => 1073741824 }
$ alter 'tariff_changes', { NAME => 'cf', SPLITS_FILE => 'splits.txt', VERSIONS => 50, MAX_FILESIZE => 1073741824 }
Split文件只有如下一行:
1 2 3 4 5 6 7 8 9 0
通过此方式告知HBase每一个分区的开始key和结束key。
具体代码是如何操作的?只编写了几个线程——每个分区一个线程——运行定制的Scan请求到key所在的分区。通过这种方式,性能有10倍的提升在上面的情景下。从30分钟
降低到3分钟。
以下是代码链接:
https://github.com/zygm0nt/hbase-distributed-search
原文地址:http://marcin.cylke.com.pl/blog/2013/12/10/distributed-scans-with-hbase/