多列上的连接是否存储笛卡尔积?



我将脚本从 T-SQL 音译为 U-SQL,并在运行作业时遇到了一个问题,即它似乎"卡"在其中一个阶段 - 2.5 小时后,作业图显示它已读取 200MB 并写入超过 3TB,但尚未完成。(没有截图,抱歉。

我将其追踪到其中一个查询,将一个包含 3400 万行的表两次连接到一个包含 1600 行的表:

@ProblemQuery = 
SELECT
gp.[Group],      // 16 groups
gp.[Percentile], // 1-100
my_fn(lt1.[Value], lt2.[Value], gp.[Value]) AS CalculatedNumber
FROM
@LargeTable AS lt1
INNER JOIN @GroupPercent AS gp
ON lt1.[Group] == gp.[Group]
AND lt1.[Row ID] == gp.[Row ID 1]
INNER JOIN @Large Table AS lt2
ON gp.[Group] == lt2.[Group]
AND gp.[Row ID 2] == lt2.[Row ID]
;

似乎在处理过程中存储了完整的笛卡尔积(~2e18 行(,而不仅仅是过滤后的 1600 行。我的第一个想法是,这可能是因为使用AND而不是&&,但改变这一点没有区别。

我设法解决这个问题,将一个具有两个联接的查询拆分为两个查询,每个查询一个联接,整个作业在 15 分钟内完成,没有存储井喷。

但是我不清楚在联接中使用多个列或错误时,这是否是完全预期的行为,以及是否有更好的方法来处理这种事情。我还有另一个类似的查询要拆分(有更多的连接,连接条件中的列更多(,我不禁觉得必须有一种不那么混乱的方式来做到这一点。

U-SQL 应用了一些连接重新排序启发式方法(尽管我不知道它如何处理明显的自连接(。我怀疑这与您在连接谓词中使用多列有关。我认为我们的启发式方法可能已经关闭。您能否提交事件或将 Microsoft dot com 的 [usql] 的工作链接发送给我?这样,我们就可以调查导致优化程序选择更差计划的原因。

在此之前,将连接拆分为两个语句,从而强制使用更好的连接顺序是最好的解决方法。

最新更新