2013-04-18 23 views
2

我有一個值列表作爲一個數據源和第二個數據集,其中包含與值相關的範圍。豬圖減少工作,將值放在適當的範圍內

Dataset 1: 
3 
4 
6 
20 
25 
38 

Dataset 2: 
1|3|A 
4|10|B 
11|20|C 
21|30|D 
31|31|E 
32|38|F 
39|40|G 

Result: 
3,A 
4,B 
6,B 
20,C 
25,D 
38,F 

我想創建某種類型的「加盟」的數據集1扳平值的字符數據集2

+0

如何大(大約)可能每個數據集是什麼? –

+0

不知道,我的猜測是,數據集1將更有可能要大一些。第二個數據集可能是一個較小的數字200k - 500k條目如果假設其中一個比另一個更大,我會好奇的看到兩個實現。 – GrkEngineer

回答

2

如果Donald Miner的任何建議能夠爲您工作的速度足夠快,我只需要做到這些,但爲了使速度更快,如果DataSet 2只有250K-500K的條目,您應該能夠將整個事件整合到內存中。因此,您可以:編寫一個將DataSet 2存儲到內存的udf(有關如何將hdfs文件存儲到DistributedCache中的信息,請參閱getCacheFiles);然後編寫一個EvalFunc,它接受DataSet A的單個項目,二進制搜索它在DataSet 2中的位置,返回答案,你想要的。

ANSWER = FOREACH DATASET1 GENERATE myBinarySearchUdf(number) 
    as myResult:Tuple(originalNumber:int, dataSet2Id:chararray); 
+0

很酷。我不知道你可以在Pig中這樣做(但它不會不會讓我感到驚訝)。代碼中的哪些地方可以將數據集加載到mem中ory,以便它不會重新加載每個UDF調用的數據集? –

+1

沒有在後端調用的初始化函數,所以在O'Reilly的豬書中他們說這是唯一的好辦法,就是懶惰地將數據集加載到exec函數的內存中,像if(dataSet == null){dataSet = initializeDataSet()}。這樣它只會在第一次通話時加載。 – DMulligan

3

的主要問題是,MapReduce的的方式做連接需要鑰匙完全匹配,並在分區器中隨機存儲事物(默認情況下)。 Java MapReduce可能有一些棘手的方法。下面是我能想到的兩個最直接的例子。不知道哪一個會更快......這取決於數據的性質。


使用跨產品:

C = CROSS A, B; 
D = FILTER C BY $1 >= $2 AND $1 <= $3; 

可能會很慢!但它完成了工作!


炸燬的範圍內,然後做一個連接

B2 = FOREACH B GENERATE FLATTEN(explode_range_udf($1, $2, $3)); 
C = JOIN A by $1, B2 by $1; 

這是你寫了一個名爲explode_range_udf UDF是發生在這三個值,並返回包含在每一個可能的元素的元組的包範圍。例如:

explode_range_udf(1,3,A) -> {(1,A),(2,A),(3,A)} 

FLATTEN創建記錄中的每件商品。