求助: 集算器测试 TPCH(Q9) 时发现的问题

大佬们,我在学习这篇文章的时候: 用 TPCH 练习性能优化 Q9 发现用 SQL 得到的结果跟用集算器得到的结果不同(我用的是 TPCH dbgen(sf=1) 的数据量)。

如下所示,SQL 结果是这样的,下图中 A2 所在格子的语句就是文章中提供的 SQL 语句:

imagepng

然后,用文中提供的 SPL 语句得到的结果比上述 SQL 结果要小很多,如下所示:

imagepng

我排查之后发现,极有可能是 A8 所在的代码格中 new@r()出现问题了,过滤掉了一部分有效的数据。按本例中测试数据量来说,orders 表有 150 万行,A7 中 lineitem 表过滤后有 32 万 8370 行,但经 A8 中的 new@r() 关联过滤之后只剩下 8 万 7716 行。此例中,orders 表是主表,lineitem 表是 orders 的子表,按照主表.new@r(子表) 的功能来看,结果集的行数应该不可能少于子表的行数,我也搞不清楚,只是无根据地猜测 new@r() 过滤掉了部分有效的数据。我按照 SPL 语句的意思,推测 A8 中的主子关联最终目的是为了得到 orders 表中的 O_ORDERDATE 列,于是从 A8 开始用 join 重新写了 SPL,此时得到的结果跟 SQL 跑出来的结果是一样的,截图和 SPL 语句如下:

imagepng

A
1 =now()
2 >name="chocolate"
3 =file("nation.btx").import@b().keys@i(N_NATIONKEY)
4 =file("part.ctx").open().cursor@m(P_PARTKEY;pos(P_NAME, name)).fetch().keys@im(P_PARTKEY)
5 =file("supplier.ctx").open().cursor@m(S_SUPPKEY,S_NATIONKEY).fetch().keys@im(S_SUPPKEY)
6 =file("partsupp.ctx").open().cursor@m(PS_PARTKEY,PS_SUPPKEY,PS_SUPPLYCOST;A4.find(PS_PARTKEY)).fetch().keys@im(PS_PARTKEY,PS_SUPPKEY)
7 =file("lineitem.ctx").open().cursor@m(L_ORDERKEY,L_PARTKEY,L_SUPPKEY,L_QUANTITY,L_EXTENDEDPRICE,L_DISCOUNT;A4.find(L_PARTKEY))
8 =file("orders.ctx").open().cursor@m().fetch()
9 =A7.join(L_ORDERKEY,A8:O_ORDERKEY,O_ORDERDATE)
10 =A9.join(L_PARTKEY:L_SUPPKEY,A6,PS_SUPPLYCOST).switch(L_SUPPKEY,A5)
11 =A10.groups(L_SUPPKEY.S_NATIONKEY:nationName,year(O_ORDERDATE):o_year;sum(L_EXTENDEDPRICE*(1-L_DISCOUNT)-PS_SUPPLYCOST*L_QUANTITY):profit)
12 =A11.run(nationName=A3.find(nationName,profit=string(profit,"0.00")).N_NAME).sort(nationName,-o_year)
13 =interval@ms(A1,now())

但又出现了另一个问题,上述代码格 A8、A9 中,A8 所在的 orders 是主表,也是维表,有 150 万行,相对于 A7 中 32 万多行的结果来说,符合较小事实表与大维表关联的场景,于是就琢磨着用游标.joinx@cq(关联字段,实表: 关联字段,实表中的字段) 来写,代码如下:

A
1 =now()
2 >name="chocolate"
3 =file("nation.btx").import@b().keys@i(N_NATIONKEY)
4 =file("part.ctx").open().cursor@m(P_PARTKEY;pos(P_NAME, name)).fetch().keys@im(P_PARTKEY)
5 =file("supplier.ctx").open().cursor@m(S_SUPPKEY,S_NATIONKEY).fetch().keys@im(S_SUPPKEY)
6 =file("partsupp.ctx").open().cursor@m(PS_PARTKEY,PS_SUPPKEY,PS_SUPPLYCOST;A4.find(PS_PARTKEY)).fetch().keys@im(PS_PARTKEY,PS_SUPPKEY)
7 =file("lineitem.ctx").open().cursor@m(L_ORDERKEY,L_PARTKEY,L_SUPPKEY,L_QUANTITY,L_EXTENDEDPRICE,L_DISCOUNT;A4.find(L_PARTKEY))
8 =file("orders.ctx").open()
9 =A7.joinx@cq(L_ORDERKEY,A8:O_ORDERKEY,O_ORDERDATE)
10 =A9.join(L_PARTKEY:L_SUPPKEY,A6,PS_SUPPLYCOST).switch(L_SUPPKEY,A5)
11 =A10.groups(L_SUPPKEY.S_NATIONKEY:nationName,year(O_ORDERDATE):o_year;sum(L_EXTENDEDPRICE*(1-L_DISCOUNT)-PS_SUPPLYCOST*L_QUANTITY):profit)
12 =A11.run(nationName=A3.find(nationName,profit=string(profit,"0.00")).N_NAME).sort(nationName,-o_year)
13 =interval@ms(A1,now())

但结果中出现了 null:

imagepng

经排查后发现,这些 null 实际上是在 joinx@cq 时没有关联上数据,在 A9 中随便找一个 null 对应的日期值去 orders 表里查,都能查得到。还有一点,这种方法得到每一个 nationname 对应的 profit 总量跟 SQL 跑出来的结果是一样的,所以,猜测 joinx@cq 时有部分有意义的数据没有关联上。

所以,我求助的问题是:

1、new@r 在本例中要如何使用才能得到跟 SQL 一样的结果?(当然也有可能是 SQL 结果出错了)
Q18 中 用 TPCH 练习性能优化 Q18 也有用 new,结果比 SQL 少了 5 行。用 join 时跟 SQL 执行结果一致。

2、小事实表.joinx@cq(大维表) 时,是不是会缺失关联数据?(也有可能是我用错了)

不管怎样,结果有出入。

恳请大佬们有空时帮忙看看这个 Q9 案例和涉及到的关联用法 new@r、joinx@cq,给予指导解惑,谢谢!

本案例测试数据集用的是 TPCH(sf=1),数据不多,但不好打包上传。需要的话请加我 QQ:12674014,烦请备注集算器字样。