Google BigQuery 查询超出资源限制

1 sql etl query-optimization google-bigquery

我正在为我的公司建立一个原始数据仓库,并且我已经成功地将联系人、公司、交易和关联数据从我们的 CRM 提取到 bigquery 中,但是当我将这些数据连接到一个主表中以通过我们的 BI 平台进行分析时,我不断收到错误:

Query exceeded resource limits. This query used 22602 CPU seconds but would charge only 40M Analysis bytes. This exceeds the ratio supported by the on-demand pricing model. Please consider moving this workload to the flat-rate reservation pricing model, which does not have this limit. 22602 CPU seconds were used, and this query must use less than 10200 CPU seconds.

因此,我正在寻求优化我的查询。我已经删除了所有GROUP BY命令ORDER BY,并尝试使用WHERE命令进行额外的过滤,但这对我来说似乎不合逻辑,因为它会增加处理需求。

我当前的查询是:

SELECT 
    coy.company_id,
    cont.contact_id,
    deals.deal_id,
    {another 52 fields}
FROM `{contacts}` AS cont
LEFT JOIN `{assoc-contact}` AS ac
ON cont.contact_id = ac.to_id
LEFT JOIN `{companies}` AS coy 
ON CAST(ac.from_id AS int64)  = coy.company_id
LEFT JOIN `{assoc-deal}` AS ad
ON coy.company_id = CAST(ad.from_id AS int64) 
LEFT JOIN `{deals}` AS deals
ON ad.to_id = deals.deal_id;
Run Code Online (Sandbox Code Playgroud)

仅供参考,{assoc-contact}{assoc-deal}都是我从关联表创建的单独视图,以便更轻松地将这些表与公司表关联。

还应该注意的是,这个查询偶尔会成功运行,所以我知道它确实有效,但由于查询太大,它在大约 90% 的情况下都会失败。

Fur*_*ine 6

太长了;

检查您的加入密钥。99% 的情况下,问题的原因是组合爆炸。

我无法确定,因为我无法访问基础表的数据,但我将提供一个通用的解决方法,根据我的经验,该方法每次都能找到根本原因。

长答案

调查方法

假设您要连接两个表

SELECT 
  cols
FROM L
JOIN R ON L.c1 = R.c1 AND L.c2 = R.c2
Run Code Online (Sandbox Code Playgroud)

你会遇到这个错误。您应该做的第一件事是检查两个表中是否有重复项。

SELECT 
  c1, c2, COUNT(1) as nb
FROM L
GROUP BY c1, c2
ORDER by nb DESC
Run Code Online (Sandbox Code Playgroud)

对于连接中涉及的每个表也是如此。

我敢打赌您会发现您的连接键是重复的。BigQuery 具有很强的可扩展性,因此根据我的经验,当您的连接键在两个表上重复超过 100 000 次时,就会发生此错误。这意味着加入后,您将拥有 100000^2 = 100 亿行!

为什么 BigQuery 会出现此错误

根据我的经验,此错误消息意味着与输入的大小相比,您的查询执行了太多计算。如果您在连接每个有几百万行的表后最终得到了 100 亿行,那么您会得到这个也就不足为奇了。

BigQuery 的按需定价模型基于表中读取的数据量。这意味着人们可能会尝试滥用这一点,例如在读取小型数据集时运行 CPU 密集型计算。举一个极端的例子,假设有人制作了一个 Javascript UDF 来挖掘比特币并在 BigQuery 上运行它

  SELECT MINE_BITCOIN_UDF()
Run Code Online (Sandbox Code Playgroud)

该查询将收取 0 美元的费用,因为它不读取任何内容,但会消耗 Google 数小时的 CPU。当然,他们必须为此做点什么。

因此,这个比率的存在是为了确保用户不会在处理几 Mb 的输入时使用数小时的 CPU 来执行任何粗略的操作。

其他具有不同定价模型的 MPP 平台(例如,Azure Synapse 根据处理的字节量收费,而不是像 BQ 那样读取)可能会毫无抱怨地运行,然后向您收取 10Tb 读取 40Mb 表的费用。

PS:抱歉这么晚又长的答案,对于提出问题的人来说可能已经太晚了,但希望它能帮助遇到该错误的人。