假设我有一个由400台机器和2个数据集组成的集群。some_dataset_1有100M条记录,some_dataset _2有1M条记录。然后我运行:
ds1:=分布式(some_dataset_1,hash(field_a));ds2:=分布式(some_dataset_2,hash(field_b));
然后,我运行加入:
j1:=JOIN(ds1,ds2,LEFT.field_a=LEFT.field _b,LOOKUP,LOCAL);
将ds2";搞砸了";连接,意味着ds2的部分将不正确地分散在集群中,导致低匹配率?
或者,LOOKUP关键字优先,分布式ds2将被完整复制到每个节点,从而使分发不相关,并允许联接找到所有可能的匹配项(因为每个节点都有ds2的完整副本)。
我知道我可以自己测试并得出自己的结论,但我正在寻找一个基于语言写作方式的明确答案,以确保我理解并正确使用这些选项。
供参考(来自语言参考文件v7.0.0):LOOKUP:指定rightrecset是一个相对较小的查找记录文件,可以完全复制到每个节点。LOCAL:指定在每个超级计算机节点上独立执行操作,无需与所有其他节点交互即可获取数据操作维护以前任何分布式的分布
似乎有了LOCAL,联接完成得更快。在最初的选拔赛中似乎没有输掉比赛。我正在与其他人合作进行更彻底的测试,并将结果发布在这里。
首先,您的代码:
ds1:=分布式(some_dataset_1,hash(field_a));
ds2:=分布式(some_dataset_2,hash(field_b));
由于您打算在JOIN中使用这些结果,因此两个数据集都必须分布在";相同的";数据,以便匹配的值最终位于相同的节点上,以便可以使用LOCAL选项完成JOIN。因此,只有当ds1.field_a和ds2.field_b包含";相同的";数据
然后,您的加入代码。我想你在这篇文章中犯了一个拼写错误,因为你的加入代码需要(才能工作):
j1:=JOIN(ds1,ds2,LEFT.field_a=RIGHT.field_b,LOOKUP,LOCAL);
同时使用LOOKUP和LOCAL选项是多余的,因为LOOKUP JOIN隐含地是一个LOCAL操作。这意味着,您的LOOKUP选项;覆盖";在这种贪得无厌的地方。
所以,所有这些都意味着你要么这样做:
ds1:=分布式(some_dataset_1,hash(field_a));
ds2:=分布式(some_dataset_2,hash(field_b));
j1:=JOIN(ds1,ds2,LEFT.field_a=RIGHT.field_b,LOCAL);
或者这样:
j1:=JOIN(some_dataset_1,some_dataset _2,LEFT.field_a=RIGHT.field_b,LOOKUP);
因为LOOKUP选项确实将整个右侧数据集(内存中)复制到每个节点,所以它使JOIN隐式地成为LOCAL操作,并且不需要执行DISTRIBUTE。你选择哪种方式做这件事取决于你自己。
然而,我从你的语言参考版本中看到,你可能不知道JOIN上的SMART选项,在我目前的语言参考(8.10.10)中说:
SMART--指定尽可能使用内存中查找,但使用如果合适的数据集很大,则进行分布式联接。
所以你可以这样做:
j1:=JOIN(some_dataset_1,some_dataset _2,LEFT.field_a=RIGHT.field_b,SMART);
让平台找出哪一个最好。
HTH,
Richard
谢谢你,Richard。是的,我因打字错误而臭名昭著。我道歉。由于我使用了很多遗留代码,我还没有机会使用SMART选项,但我肯定会为我和团队保留这一点,所以谢谢你!
然而,我确实运行了一个测试来评估编译器和平台将如何处理这种情况。我运行了以下代码:
sd1:=DATASET(100000,TRANSFORM({unsigned8 num1},SELF.num1 := COUNTER ));
sd2:=DATASET(1000,TRANSFORM({unsigned8 num1, unsigned8 num2},SELF.num1 := COUNTER , SELF.num2 := COUNTER % 10 ));
ds1:=DISTRIBUTE(sd1,hash(num1));
ds4:=DISTRIBUTE(sd1,random());
ds2:=DISTRIBUTE(sd2,hash(num1));
ds3:=DISTRIBUTE(sd2,hash(num2));
j11:=JOIN(sd1,sd2,LEFT.num1=RIGHT.num1 ):independent;
j12:=JOIN(sd1,sd2,LEFT.num1=RIGHT.num1,LOOKUP ):independent;
j13:=JOIN(sd1,sd2,LEFT.num1=RIGHT.num1, LOCAL):independent;
j14:=JOIN(sd1,sd2,LEFT.num1=RIGHT.num1,LOOKUP,LOCAL):independent;
j21:=JOIN(ds1,ds2,LEFT.num1=RIGHT.num1 ):independent;
j22:=JOIN(ds1,ds2,LEFT.num1=RIGHT.num1,LOOKUP ):independent;
j23:=JOIN(ds1,ds2,LEFT.num1=RIGHT.num1, LOCAL):independent;
j24:=JOIN(ds1,ds2,LEFT.num1=RIGHT.num1,LOOKUP,LOCAL):independent;
j31:=JOIN(ds1,ds3,LEFT.num1=RIGHT.num1 ):independent;
j32:=JOIN(ds1,ds3,LEFT.num1=RIGHT.num1,LOOKUP ):independent;
j33:=JOIN(ds1,ds3,LEFT.num1=RIGHT.num1, LOCAL):independent;
j34:=JOIN(ds1,ds3,LEFT.num1=RIGHT.num1,LOOKUP,LOCAL):independent;
j41:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1 ):independent;
j42:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1,LOOKUP ):independent;
j43:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1, LOCAL):independent;
j44:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1,LOOKUP,LOCAL):independent;
j51:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1 ):independent;
j52:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1,LOOKUP ):independent;
j53:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1, LOCAL,HASH):independent;
j54:=JOIN(ds4,ds2,LEFT.num1=RIGHT.num1,LOOKUP,LOCAL,HASH):independent;
dataset([{count(j11),'11'},{count(j12),'12'},{count(j13),'13'},{count(j14),'14'},
{count(j21),'21'},{count(j22),'22'},{count(j23),'23'},{count(j24),'24'},
{count(j31),'31'},{count(j32),'32'},{count(j33),'33'},{count(j34),'34'},
{count(j31),'41'},{count(j32),'42'},{count(j33),'43'},{count(j44),'44'},
{count(j51),'51'},{count(j52),'52'},{count(j53),'53'},{count(j54),'54'}
] , {unsigned8 num, string lbl});
在一个400节点的集群上,结果返回为:
## | num | lbl//tr>|
---|---|---|
1 | 1000 | 11 |
2 | 1000 | 12 |
3 | 1000 | 13 |
4 | 1000 | 14 |
5 | 1000 | 21 |
6 | 1000 | 22 |
7 | 1000 | 23 |
8 | 1000 | 24 |
9 | 1000 | 31 |
10 | 1000 | 32 |
11 | 22 | 33[/tr>|
12 | 22 | 34 |
13 | 1000 | 41 |
14 | 1000 | 42 |
15 | 12 | 43 |
16 | 44 | |
17 | 1000 | 51 |
18 | 1000 | 52 |
19 | 1 | 53 |
20 | 1 | 54 |
手册页面可能会更好LOOKUP本身已正确记录。并且LOCAL本身被适当地记录。然而,它们代表两个不同的概念,可以毫无问题地组合在一起,因此JOIN(,,LOOKUP,LOCAL)是有意义的,也是有用的。
最好将LOOKUP视为一种特定类型的JOIN匹配算法,并将LOCAL作为一种方式来告诉编译器您不是新手,并且您绝对确信数据已经达到了实现您想要的目标所需的位置。
对于一个普通的LOOKUP联接,左手边不需要以任何特定的方式进行排序或分布,整个右手边都会复制到每个从节点。无论LEFT上出现什么联接值,如果RIGHT上有匹配的值,则会找到它,因为整个RIGHT数据集都存在。
在具有良好分布的联接值的400路系统中,如果LEFT侧分布在联接值上,则每个工作者中的LEFT数据集只包含联接值的1/400,并且RIGHT数据集中的值只有1/400将被匹配。实际上,在每个工作者中,第399/400个RIGHT数据将未使用。
但是,如果LEFT和RIGHT数据集都分布在联接值上。。。并且您不是新手,并且知道使用LOCAL是您想要的。。。则可以指定LOOKUP、LOCAL联接。RIGHT数据已经位于需要的位置。如果LEFT数据中出现的任何联接值存在,则该值将在RIGHT数据集中本地找到匹配项。作为奖励,RIGHT数据只包含可能与…匹配的联接值。。。它仅为LOOKUP唯一大小的1/400。
这样可以实现更大的LOOKUP联接。想象一下您的400路系统和100GB RIGHT数据集,您想在LOOKUP联接中使用该数据集。将100GB的数据集复制到每个从属服务器似乎不太可能奏效。但是,如果分布均匀,LOOKUP、LOCAL联接每个工作线程只需要250MB的RIGHT数据。。。这似乎很合理。
HTH-