我有一个查询,它基本上根据几个条件从表中获取几个列,然后进行更新。并且,所有这些操作都在循环中运行 - 即。对于从选择查询中找到的每条记录,它都会执行更新操作,这会严重影响性能。
for temp in
(
select a, b, c, d
from tbl1
where
a in
(select w2.a from tbl1 w2
where cast(w2.c as int64) > 0 and
trim(w2.d) = ''
)
and
b in
(select w2.b from tbl1 w2
where cast(w2.c as int64) > 0 and trim(w2.d) = ''
)
and cast(c as int64) = 0
order by a, b, c
)
do
update tbl1 wrkup
set wrkup.d = temp.d
where wrkup.a = temp.a
and wrkup.b = temp.b
and cast(wrkup.c as int64) > 0
and trim(wrkup.d ) = '';
end for;
上面的查询花了1小时23分钟更新了1146条语句,tbl1总共有419668条记录。 请看,我正在 for 循环中读取同一个表tbl1,然后根据不同的条件对其进行更新。
我确实检查了这篇文章:(https://medium.com/google-cloud/bigquery-looping-optimization-8d575e4b72d0#:~:text=Looping%20is%20a%20sequence%20of%20actions%20that%20is% 20连续%20重复,迭代%20将%20不%20获取%20触发) 但是,实施起来有点复杂。所以,想知道是否有更简单的方法来解决这个问题。
您的设计问题是 SQL 脚本按顺序运行查询。优化处理的方法是并行化处理。为此,您必须在外部进行。
通常,您可以使用脚本(python)来运行“for”查询。在每一行(如果我理解正确的话是 1146),您可以使用该行的数据创建一个 PubSub 消息或云任务
然后插入另一个处理单元,例如获取消息数据的 Cloud Run 或 Cloud Functions,并在 BigQuery 中运行“do”。这样,您就可以并行化所有请求。
如果出现问题,特别是超出配额,您应该达到的配额,查询将失败,但消息将重新提交。无论如何,最终您可以将持续时间缩短 10 倍甚至 100 倍。