为什么多个连接需要永远?

时间:2015-01-27 21:14:20

标签: google-bigquery

我相信我在Google BigQuery中发现了一个错误,但我不确定。 我希望有人可以提供解决方法。

我在一张只有200K数据的桌子上运行的表。

在我尝试进行漏斗分析时,我偶然发现了以下奇怪的行为:

这需要约3秒钟:

SELECT
  COUNT(DISTINCT Q0._user_id) AS step0
FROM
  (SELECT _user_id FROM [5629499534213120.201501]) AS Q0
LEFT OUTER JOIN
  (SELECT _user_id, _time FROM [5629499534213120.201501] WHERE _os=='Windows') AS Q1
ON (Q0._user_id=Q1._user_id)

这需要 ~3分钟

SELECT
  COUNT(DISTINCT Q0._user_id) AS step0
FROM
  (SELECT _user_id FROM [5629499534213120.201501]) AS Q0
LEFT OUTER JOIN
  (SELECT _user_id, _time FROM [5629499534213120.201501] WHERE _os=='Windows') AS Q1
ON (Q0._user_id=Q1._user_id)
LEFT OUTER JOIN
  (SELECT _user_id, _time FROM [5629499534213120.201501] WHERE _country=='de') AS Q2
ON (Q0._user_id=Q2._user_id)

意味着再添加一个Left Join会使查询变得非常慢(我们只讨论的是200k的数据)。

显然,我已经简化了Select语句,因此您可以专注于主要问题(我使用的真正的选择语句要复杂得多)

有谁知道问题是什么,或者解决方法是什么?

2 个答案:

答案 0 :(得分:5)

我在BigQuery问题跟踪器上回复了这个问题,但我在这里重新发布了答案:

我是一名大型工程师,我在日志中查询了您的查询。 您所看到的是加入爆炸。

您使用非唯一键进行了3向自连接。字段“_user_id”具有单个值,左侧匹配3937行,第一个联接中匹配1388行,第二个联接中匹配1388行。

这意味着您要创建3937 * 1388 * 1488或75亿输出行。 (然后,您对它们进行了不同的计数以减小输出大小,但需要首先创建中间值)。

创建75亿个中间行需要花费几分钟就不足为奇了,特别是因为它们都来自一个密钥,因此必须由单个工作任务生成。

我的猜测是,可以重新构建查询以避免连接爆炸。

答案 1 :(得分:0)

我不熟悉BigQuery,但我怀疑内部查询(SELECT _user_id, _time FROM [...)正在检索整个表。

如何重新编写查询如下:

SELECT
  COUNT(DISTINCT Q0._user_id) AS step0
FROM
  [5629499534213120.201501] AS Q0
LEFT OUTER JOIN [5629499534213120.201501] AS Q1
  ON (Q0._user_id=Q1._user_id)
LEFT OUTER JOIN [5629499534213120.201501] AS Q2
  ON (Q0._user_id=Q2._user_id)
WHERE Q1._os=='Windows'
  AND Q2._country=='de'

据我所知,结果应该是一样的;这样的措辞应该有希望允许数据库使用索引(如果数据库正确规范化)。