BigQuery相互之间的连接速度更快

ala*_*lan 1 cross-join google-bigquery

我正在尝试按日期查看用户活动。第一步是使用交叉连接和where子句,创建自创建用户帐户以来每天的表格。我的第一次尝试是:

SELECT
  u.user_id as user_id,
  date(u.created) as signup_date,
  cal.date as date,

from rsdw.user u
  cross join (select date(dt) as date from [rsdw.calendar] where date(dt) < CURRENT_DATE() ) cal
where
  date(u.created) <= cal.date
Run Code Online (Sandbox Code Playgroud)

(日历表只是2006年以来所有日期的列表(3288行)。用户表有约100万行。)

这个查询要花很长时间……太久了,以至于我在1000秒钟左右就放弃了它。我试着稍微调整查询。如果我向交叉联接添加“每个”:

SELECT
  u.user_id as user_id,
  date(u.created) as signup_date,
  cal.date as date,

from rsdw.user u
  cross join each (select date(dt) as date from [rsdw.calendar] where date(dt) < CURRENT_DATE() ) cal
where
  date(u.created) <= cal.date
Run Code Online (Sandbox Code Playgroud)

我得到一个错误:

Error: Cannot CROSS JOIN two tables with EACH qualifiers.
Run Code Online (Sandbox Code Playgroud)

最后,如果我保留“每个”但交换表,则只需90秒钟即可完成!

SELECT
  u.user_id as user_id,
  date(u.created) as signup_date,
  cal.date as date,

from (select date(dt) as date from [rsdw.calendar] where date(dt) < CURRENT_DATE() ) cal
  cross join each rsdw.user u
where
  date(u.created) <= cal.date
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么第三次迭代如此之快,为什么第二次迭代会导致错误?

小智 5

您正在了解联接​​如何与子选择子句交互的一些极端情况。针对命名表的联接受益于基于表大小的一些优化,而子选择是不可预测的,并且可能导致性能下降。我已为我们提交了一个内部错误,以改善此情况。

在第一种慢速情况下,您将日期的微小子选择复制并广播到少量计算机,每个计算机都处理大量用户。由于几乎没有并行性,因此需要永远做。

第二种情况是由于内部原因导致的查询解析错误,基本上是试图使计算机同时处理较小范围的日期和较小范围的用户,这将无法完成交叉联接。

在第三个快速案例中,您将日期的微小子选择复制并广播到许多机器,每台机器都处理少量用户。由于具有较大的并行性,它可以非常快速地完成。

一旦完成我提交的错误,第三种情况下的行为有望自动发生。