Understanding Cubert Concepts(二):Cubert Co-Partitioned Blocks
話接上文Cubert PartitionedBlocks,我們介紹了Cubert的核心Block概念之一的分區塊,它是一種根據
partitionKeys
和
cost function
來對原始資料進行
Redistribution
和
Transformation
來結構化資料,這種結構化的資料是對後續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 P的
parititionKey
指定為memberId,那麼
BLOCKGEN
過程後,會生成類似如下的索引:
memberIds from to => block
memberIds from to => block
and so on until block N
至此,我們做的都是
PartitionedBlocks
,如果
dataset **S**
要生成
Co-paritionedBlocks
怎麼辦呢? 那麼
索引
就是
dataset **P**
.
- BLOCKGEN For DataSet S (
)Co-partitionedBlocks
我們要生成與DataSet P 同樣
number
的
blocks
。(分區都是一緻的)
具體來說,就是
block i of S
會和
block i in P
有着相同的
memberIds
,換句話說,如果
memberId=1234
在
block 2 of P
中,那麼我們能确定能在
block 2 of S
中找到這個相同的
memberId
.
對于
Map-Side Join
來說,這種
一緻性的分區方法
是必要的。
這種根據其它已經partitionedBlock來進行建立一緻性分區Block的過程叫做
BLOCKGEN BY INDEX
BLOCKGEN BY INDEX Checklist
如果想要使用cubert來進行開發,那麼我們必須遵從下面三個準則:
- 定義primary relation:也就是上面我們建立的
,指定我們要使用的index,這樣我們可以根據這個index來建立BLOCKS。(Ps:這裡的說的index,就是primary relation)DataSet P
Note:
是一個可傳遞性的操作,比如,我們有三個資料集A,B,C。我們通過BLOCKGEN BY INDEX
操作資料集A,然後我們可以将BLOKGEN
作為A
,這樣我們就可以根據primary relation (可以看做indexA)
建立indexA
。現在如果C也要做co-partitioned Blocks
操作怎麼辦呢,選用A還是B呢?其實這種BLOCKGEN
是傳遞性的,indexA -> Blocks of B (co-partitioned), 那麼indexA -> Blocks of C 後, Blocks of B == Blocks of C(這裡BLOCKGEN BY INDEX
==
的意思是co-partitioned).
是以說
是一個可傳遞性的操作。BLOCKGEN BY INDEX
-
定義SortKeys(可選)
這個排序也是在每個生成後的block内進行的(根據sortKeys排序),不是全局排序的。
-
存儲為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 BLOCKGEN
為其索引的。target path
eg:
// the primary dataset
JOB "our first BLOCKGEN"
REDUCERS ;
MAP {
data = LOAD "/path/to/data" USING AVRO();
}
//根據memberId來作為分區鍵,根據timestamp來進行sort
BLOCKGEN data BY ROW 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 ;
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後的資料集重新從存儲路徑(
)使用RUBIX FILE FORMAT加載進來/path/to/output
- 使用相同的路徑自引用索引
來/path/to/output
,并且指定BLOCKGEN BY INDEX
重排序的鍵為sorted on pagekey
pagekey
JOB "resorting blocks"
REDUCERS ;
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
- 并且一定要使用相同的
哦,否則block的資料分布就亂了。partition Keys
同樣,我們可以對資料集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)協定,歡迎轉載、轉發和評論,但是請保留本文作者署名和文章連結。如若需要用于商業目的或者與授權方面的協商,請聯系我。