您的位置:首页 > 其它

关于分区有序数据merge的解决方案

2013-10-30 00:49 246 查看

一,基本概念

什么是分区数据?如果一张表被水平切分,比如切分成100张相同的表。通过sharding策略把数据分别存放在这100张表中,那么称这100张表的每一张表为一个分区。它们共同组成了这个同类型的数据表。

提供一个例子供以后分析 如:

1,user表分成100个region

2,sharding策略:按照user_id%100决定放到哪个分区。

3,user表有一个age字段

二,分区数据合并的情形

如果分区的sharding策略不是按照某个条件做的range分区。上面例子就明显不是按照user_id的range分区。如果要对例子中的user做如下查询。

select * from user where age>10 order by age limit 100;

对于这个查询,要对这100个表做merge然后取出100条(如果存在100条);

作者以及作者之前的一些同事,以为对于这种merge需要每个region取出100条,然后merge sort,最终取出100条。那么就是在上面的top100也需要查询100*100到内存(假设region数据有足够多),想想,如果取的不是top100,而是一直向下翻页,那么将是timeout 和oom的竞争。上周周末公司邀请了一位淘宝牛人做互联网架构分享,居然他们之前region merge也是这样做的。所以决定把在读hbase代码时发现的优秀方案分享一下。hbase scan时需要memstore和storefile做heap
merge。

三,解决方案

利用分区有序。

如上个场景可以对于,每个region执行如下sql(主要做原理说明,至于是否是每个region的分页大小 region_page=10,需要根据条件给一个合理值)

select * from user where age>10 order by age limit 10;

这样每个region取出10条数据,总取出100条,然后对于每个region数据进行遍历。

遍历方式如下:

每个region先拿出第一条数据来比较,这一条一定是每个region中查询出来最小的那条数据。这样可以选出这100个region中最小的那条数据。不妨假设这条数据在第20这个region中,然后拿出第20这个region中的第二条数据与其他region中的第一条数据做比较。这样可以选出这100个region中第二小的那条数据。依次类推,如果某个region的这10条数据都取出去了,就再拿10条。直到100条为止。

像这样merge

乐观情况: 只需要查询100条数据就可以找到100个有序数据

悲观情况: 也只需要查询200条数据

如果需要分页,其实就是跳过前面的页数,比如查询limit 100,100。那么只需要跳过前100条,从101条开始计数即可!切记,这里不能直接做分区分页,分区的查询还是需要按照上述的查询。否则得不到正确结果!查询页数越多越慢,这是必然的,RDBMS也是一样,这是没有捷径的!

需要扫过的数据的计算公式如下

limit*(page) =< datas <=limit*(page+1),(page从1开始)

节省了内存,也省了数据库查询压力。

当然可能要多几次IO,这取决于每次从每个分区取出的数据,以及limit,以及分区命中情况

多出的IO范围计算如下:

0=< IO_times <= limit/region_page

所以如果分页足够多,limit比较大region_page可以适当调大,当然要有一个合理上限,可以根据可用内存,以及GC情况而定!

region_page的建议公式如下:

min(10000,limit*page)/regions=< region_page <=min(limit*(page+1),10000)/regions;

是否取region_page = min(limit*(page+1),10000)/(2*regions)比较好,呵呵,这个具体而定吧,不纠结!

四,总结

利用region有序,然后对于找到值的region向下迭代。可以找出全局顺序!

需要对region page size合理计算。

可能会出现time_out,但是不会出现OOM(除非你的内存小到,只取出两条数据就OOM了)。

这种方案在不考虑性能的情况下,确实是可以先从任意两个region取出一条数据进行比较,但是这是走向time_out的节奏!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐