【性能优化】9.2 [集群] 集群复组表
9.2 集群复组表
对于数据表上的常规运算,使用 fork 写起来有些麻烦,SPL 也提供了集群表和集群游标来简化代码,但情况要比单机复杂一些。
回顾第二章出现的复组表概念。为了方便删除旧数据,复组表可以由多个物理文件构成,即分区;每个物理文件均有个编号,即分区号。
复组表的分区还可以分布在集群的分机上。先看简单的情况:复组表的分区数量和集群中的分机数量相同,且每个分机有一个分区。
A |
|
1 |
["192.168.0.101:8281","192.168.0.102:8281",…, "192.168.0.104:8281"] |
2 |
=file@w("orders.ctx":to(4),A1) |
3 |
=A2.create(…;(day(dt)-1)%4+1) |
4 |
=A3.append(…) |
用 file@w 创建可写的集群文件,4 个分区和分机一一对应,即会在第 i 个分机上产生第 i 个分区文件,然后再创建集群组表,然后追加数据。注意有分区的复组表需要有个分区表达式(和单机时是一样的)。
计算时除了创建文件不同外,其它语法和单机时基本一样:
A |
|
1 |
["192.168.0.101:8281","192.168.0.102:8281",…, "192.168.0.104:8281"] |
2 |
=file("orders.ctx":[1,2,3,4],A1) |
3 |
=A2.open() |
4 |
=A3.cursor@m(area,amount;dt>=arg1 && dt<arg2;4) |
5 |
=A4.groups(area;sum(amount)) |
A2 创建集群文件时也要把分区号写上,因为复组表允许不使用所有分区。SPL 会按一定规则到各个分机上寻找到相应的分区。基于集群文件创建的组表和游标称为集群表和集群游标,然后就可以完成相关运算。
回顾上一节所述的多机并行框架,分机各自计算后将结果传送给主机汇总,分机计算过程中互相之间没有数据交换。这个并行框基于集群表的分区机制实施时,每个分机只要处理自己保有的分区数据,不依赖于其它分机,和单机运算时几乎一样。这样,许多运算都可以简单地从单机移植到集群上,而且有了集群表语法后的代码书写也和单机时很像。
我们简单阐述一下这些常见运算的工作原理,不再详细举例。
无索引查找可以直接套用这个框架和语法。
索引有两种办法处理。简单的办法是对每个分机单独建立索引,那么可以依然使用这个框架,在查找时每个分机是独立的,分别查找出结果后再返回主机汇总。这样,每次查找都要动用所有分机,消耗资源较多。复杂的办法是把索引也建立成有分区的并按分区排序,根据查找值可以立即定位索引的分区并找到目标值所在位置,对于精确查找(返回结果集只有一条),只需要两个分机有动作(索引所在分区和目标值所在分区),消耗资源较小。对于单任务,两种办法几乎没有性能差异,但对于并发较多且需要极致性能的场景,后者会更有优势。
过滤以及常规的小分组也可以套用这个框架和语法。
有序分组(以及其它各种有序遍历)时需要注意,不能把相同分组键值的记录分到不同分区。这一点通常很容易被满足。
在这种框架下,大分组(大排序)使用排序算法会更简单,分机分别分组(排序)后,汇总到主机上时要保持对分组键(排序表达式)有序再做最后的归并。在分机上也可以使用哈希大分组,但仍要把结果传输到主机上归并,也仍然需要某种序。使用按哈希值的次序,哈希值相同时再按分组键排序,也可以完成最后的归并,但相对麻烦一些。 这种框架的缺点在于会将最后的归并计算量都压在主机上,导致主机的计算能力和网络容量成为瓶颈。
上述这些单表运算相对容易实现分布式计算。除了最后要向主机传输分机的运算结果外,在运算的大部分时间内,分机是独立的,之间并没有数据传输。扩展集群规模也不会加大网络负担,却能有效地分担计算量。
分布式数据库对于单表运算的集群化通常也是这种方法,不会造成分机之间过多的网络传输。不过,有些数据库做大分组时采用哈希方法,会在分机之间分发数据(将哈希值相同的记录分发到同一个分机再去单机分组),好处在于由分机来分担汇总计算量(相当于上述框架中最后的归并动作),但大量的网络传输会导致集群规模受限,到一定限度时,再增加分机数量并不会使运算性能加大。
连接运算要分情况讨论。同维关联和主子关联相对简单,只要做好数据分布,使关联表中相同主键的数据分到相同的分区号,这样就可以保证关联的数据都在同一个分区(也就在同一个分机),分机之间也就不需要数据传输。这里要求的数据分布只和主键有关,和要求主键有序类似,在数据整理和追加时稍加处理即可,也不是很难被满足。数据分布合适之后,运算代码仍然和单机是一样的。
外键关联中的维表需要被随机访问,情况要更复杂,我们下面分两节讨论。
数据库不区分连接运算的各种情况,常见方法就是把单机的哈希方法扩展集群上,每个分机根据哈希值将本机数据分发到各个分机(形成缓存),确保相关联的数据都在同一个分机,然后再在每个分机上做单机连接。这种算法的前一步分发过程将产生大量的网络传输量,也会发生集群规模受限的现象,多机分担计算量带来的性能提升会完全被传输造成的性能下降抵消掉,再增加分机也不会提高性能了。连接运算一直是分布式数据库的困难问题。