Understanding Cubert Concepts(二)Co-Partitioned Blocks

Understanding Cubert Concepts(二):Cubert Co-Partitioned Blocks

话接上文Cubert PartitionedBlocks,我们介绍了Cubert的核心Block概念之一的分区块,它是一种根据partitionKeyscost function来对原始数据进行RedistributionTransformation来结构化数据,这种结构化的数据是对后续join和cube计算是非常有利的。

好了,本文将着重讲Cubert Block中的另一种Block,Co-PartitionedBlock.

Co-partitioned Blocks

让我们来看下另一种创建blocks的方式:
这种方式就是,依靠一个dataset的index创建``另一个dataset的blocks.
比如:
有一个dataset P 是通过上文Cubert PartitionedBlocks的BLOCKGEN方式生成的。这个dataset P 的内部会将partitionKeys的全局的range划分为sub-ranges,使得每个sub-range的key范围对应了一个block.(Ps:就是定范围的rangeKeys的数据在一个block内)

举个例子:

  • BLOCKGEN For DataSet P (PartitionedBlocks)

比如我们对dataset PparititionKey指定为memberId,那么BLOCKGEN过程后,会生成类似如下的索引:

memberIds from 0 to 1000 => block 0
memberIds from 1001 to 1500 => block 1
and so on until block N

至此,我们做的都是PartitionedBlocks,如果dataset **S** 要生成Co-paritionedBlocks怎么办呢? 那么索引就是dataset **P**.

  • BLOCKGEN For DataSet S (Co-partitionedBlocks)

我们要生成与DataSet P 同样numberblocks。(分区都是一致的)

具体来说,就是block i of S会和block i in P有着相同的memberIds,换句话说,如果memberId=1234block 2 of P中,那么我们能确定能在block 2 of S中找到这个相同的memberId.

对于Map-Side Join来说,这种一致性的分区方法是必要的。

这种根据其它已经partitionedBlock来进行创建一致性分区Block的过程叫做BLOCKGEN BY INDEX

BLOCKGEN BY INDEX Checklist

如果想要使用cubert来进行开发,那么我们必须遵从下面三个准则:

  1. 定义primary relation:也就是上面我们创建的DataSet P,指定我们要使用的index,这样我们可以根据这个index来创建BLOCKS。(Ps:这里的说的index,就是primary relation)

    Note:
    BLOCKGEN BY INDEX是一个可传递性的操作,比如,我们有三个数据集A,B,C。我们通过BLOKGEN操作数据集A,然后我们可以将A作为primary relation (可以看做indexA),这样我们就可以根据indexA创建co-partitioned Blocks。现在如果C也要做BLOCKGEN操作怎么办呢,选用A还是B呢?其实这种BLOCKGEN BY INDEX是传递性的,indexA -> Blocks of B (co-partitioned), 那么indexA -> Blocks of C 后, Blocks of B == Blocks of C(这里==的意思是co-partitioned).
    所以说BLOCKGEN BY INDEX是一个可传递性的操作。

  2. 定义SortKeys(可选)
    这个排序也是在每个生成后的block内进行的(根据sortKeys排序),不是全局排序的。

  3. 存储为RUBIX FILE FORMAT
    原始数据集转化为blocks的操作,存储的格式必须为RUBIX FILE FOMRAT。

Creating Co-Partitioned Blocks

要创建Co-PartitionedBlocks,还是需要BLOCKGEN这个shuffle command,通过使用BY INDEX来生成。

  • 首先第一个JOB生成primary dataset(包含index,存储的路径就是下面要生成co-partitionedBlocks的索引路径)
  • 第二个BlockGen是通过BY INDEX 指定第primary dataset BLOCKGENtarget path为其索引的。

eg:

// the primary dataset
JOB "our first BLOCKGEN"
        REDUCERS 10;
        MAP {
                data = LOAD "/path/to/data" USING AVRO();
        }
        //根据memberId来作为分区键,根据timestamp来进行sort
        BLOCKGEN data BY ROW 1000 PARTITIONED ON memberId SORTED ON timestamp;
        //注意,这里必须存储为RUBIX FILE FORMAT
        STORE data INTO "/path/to/output" USING RUBIX();
END

JOB "our first blockgen by index"
        REDUCERS 20;
        MAP {
                data = LOAD "/path/to/other/data" USING AVRO();
        }

        //注意 INDEX的 Path 为 上一个JOB的存储目录
        BLOCKGEN data BY INDEX "/path/to/output" PARTITIONED ON memberId SORTED ON some_column;
        STORE data INTO "/path/to/other/output" USING RUBIX();
END

Idiom of Resorting Blocks

BLOCKGEN BY INDE命令还有另一种用途,对于已创建过的Blocks进行重新排序

在上一个例子里的our first BLOCKGEN JOB里,我们是对blocks内部根据timestamp键来进行排序的。如果我想重新指定排序键,怎么做呢?

  • 将生成Blocks后的数据集重新从存储路径(/path/to/output)使用RUBIX FILE FORMAT加载进来
  • 使用相同的路径自引用索引/path/to/outputBLOCKGEN BY INDEX,并且指定sorted on pagekey 重排序的键为pagekey
JOB "resorting blocks"
        REDUCERS 10;
        MAP {
                data = LOAD "/path/to/output" USING RUBIX();
        }
        BLOCKGEN data BY INDEX "/path/to/output" PARTITIONED ON memberId SORTED ON pagekey;
        STORE data INTO "/path/to/resorted-output" USING RUBIX();
END

注意:

  • 我们要确保使用的还是原始数据集的index
  • 并且一定要使用相同的partition Keys哦,否则block的数据分布就乱了。

同样,我们可以对数据集B,C都使用indexA进行重排序处理,因为他们都是co-partitioned blocks

参考

Cubert官方文档blocks

Ps:本文的写作是基于对Cubert官方文档的翻译和个人对Cubert的理解综合完成 :)

原创文章,转载请注明:

转载自:OopsOutOfMemory盛利的Blog,作者: OopsOutOfMemory

本文链接地址:http://blog.csdn.net/oopsoom/article/details/46707733

注:本文基于署名-非商业性使用-禁止演绎 2.5 中国大陆(CC BY-NC-ND 2.5 CN)协议,欢迎转载、转发和评论,但是请保留本文作者署名和文章链接。如若需要用于商业目的或者与授权方面的协商,请联系我。

你可能感兴趣的:(cubert)