Google bigquery 为什么多个连接要花很长时间?

Google bigquery 为什么多个连接要花很长时间?,google-bigquery,Google Bigquery,我相信我在Google BigQuery中发现了一个bug,但我不确定。 我希望有人能提供一个解决办法 我在一个只有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,

我相信我在Google BigQuery中发现了一个bug,但我不确定。 我希望有人能提供一个解决办法

我在一个只有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分钟:

这意味着再添加一个左连接会使查询速度慢得令人难以置信——我们所说的数据量只有200k

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


有人知道问题出在哪里吗?或者有什么解决方法吗?

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

我是一名bigquery工程师,我在我们的日志中查找了您的查询。 你看到的是一个连接爆炸

您使用非唯一键进行了3路自联接。字段_user_id有一个值,该值与左侧的3937行、第一个联接中的1388行和第二个联接中的1388行相匹配

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

创建75亿个中间行需要几分钟,这并不奇怪,特别是因为它们都来自一个键,因此必须由单个辅助任务生成


我的猜测是,可以重新构造查询以避免加入爆炸。

我在BigQuery问题跟踪器上对此做出了回应,但我将我的答案重新发布在这里:

我是一名bigquery工程师,我在我们的日志中查找了您的查询。 你看到的是一个连接爆炸

您使用非唯一键进行了3路自联接。字段_user_id有一个值,该值与左侧的3937行、第一个联接中的1388行和第二个联接中的1388行相匹配

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

创建75亿个中间行需要几分钟,这并不奇怪,特别是因为它们都来自一个键,因此必须由单个辅助任务生成


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

我不太熟悉BigQuery,但我怀疑内部查询SELECT _user _id,_TIMEFROM[…]正在检索整个表

按照以下方式重新编写查询怎么样:

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'

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

我不太熟悉BigQuery,但我怀疑内部查询SELECT _user _id,_TIMEFROM[…正在检索整个表

按照以下方式重新编写查询怎么样:

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'

据我所知,结果应该是一样的;如果数据库正常化,这样的措辞应该允许数据库使用索引。

离开外部联接时会发生什么[5629499534213120.201501]正如Q0上的Q2.\u user\u id=Q2.\u user\u id和Q2.\u country='de'?我认为您的内部查询可能会破坏使用IndexOn子句必须是和of=比较每个表中一个字段名的能力,所有字段名都以表名为前缀。好的,将Q2.\u country='de'移动到WHERE子句如何?如果我理解正确,您的意思是一个n外部WHERE子句?但这会损害我对外部联接所做的操作。您可以提交一个示例来说明您的意思吗?当您离开外部联接时会发生什么[5629499534213120.201501]正如Q0上的Q2.\u user\u id=Q2.\u user\u id和Q2.\u country='de'?我认为您的内部查询可能会破坏使用IndexOn子句必须是和of=比较每个表中一个字段名的能力,所有字段名都以表名为前缀。好的,将Q2.\u country='de'移动到WHERE子句如何?如果我理解正确,您的意思是一个n EXTER WHERE子句?但这会损害我试图对外部联接所做的操作。您可以提交一个示例来说明您的意思吗?嗨,Jordan,非常感谢您的回答:。希望您不介意在问题追踪器上继续此操作。也许可以吗?您可以帮助我重建查询,然后我将在这里为大家报告修改后的查询参考。这是供任何想关注的人使用的链接:嗨,Jordan,非常感谢你的回答:。希望你不介意在问题追踪器上继续此操作。也许可以吧?你可以帮助我重建查询,然后我会在这里报告修改后的查询供大家参考。这是供任何想关注的人使用的链接:结果w与复杂的select语句不同,记住其目的是创建fu
内尔。步骤0,步骤1,步骤2不同的步骤,不同的条件。我相信是漏斗导致了连接爆炸;如果单个select正在停止数据库select,则结果与复杂的select语句不同,请记住,其目的是创建漏斗。步骤0,步骤1,步骤2不同的步骤,不同的条件。我相信是漏斗导致了连接爆炸;单个select正在阻止数据库select的智能化