我已经按需要订购了一张大表(约5900万行,7.1 GB),我想查询该表并为该表的每一行获取row_number()。 不幸的是我得到了错误 “查询执行期间超出了资源:无法在分配的内存中执行查询。”
有没有办法增加BigQuery中分配的内存?
这是我的查询,我不知道如何简化它,但是如果您有任何建议,我会接受
SELECT
row_number() over() as rowNumber,
game,
app_version,
event_date,
user_pseudo_id,
event_name,
event_timestamp,
country,
platform
FROM
`mediation_time_BASE`
这是完整的错误消息:
查询执行期间超出了资源:无法在分配的内存中执行查询。高峰使用:限制的146%。内存消耗最大的用户:解析OVER()子句:98%其他/未分配:2%
编辑: 这里的查询代表事件开始和结束的列表,我需要将start事件与其结束链接,因此我遵循以下提示:https://www.interfacett.com/blogs/how-to-use-values-from-previous-or-next-rows-in-a-query-in-sql-server/ 为此,我需要具有row_number()的行,以便将该子查询分成2个(事件以一只手开始,事件以另一只手结束),将它们连接起来,然后每个事件都有一行,其开头和结尾为事件,如下所示(其中子查询代表具有row_number()的查询):
SELECT
(case when lead(inter.rowNumber) OVER(ORDER BY inter.rowNumber) - inter.rownumber =1
then lead(inter.rowNumber) OVER(ORDER BY inter.rowNumber)
else inter.rownumber end) as rowNumber,
min(inter_success.rowNumber) as rowNumber_success,
inter.game,
inter.app_version,
inter.event_date,
inter.user_pseudo_id,
inter.event_timestamp as event_start,
min(inter_success.event_timestamp) as event_end,
inter_success.event_name as results
FROM
(SELECT * FROM `subquery` where event_name = 'interstitial_fetch') as inter INNER JOIN
(SELECT * FROM `subquery` where event_name = 'interstitial_fetch_success') as inter_success
ON inter.rowNumber < inter_success.rowNumber and inter.game= inter_success.game and inter.app_version = inter_success.app_version and inter.user_pseudo_id = inter_success.user_pseudo_id
GROUP BY inter.rowNumber,inter.game,inter.app_version,inter.event_date,inter.user_pseudo_id,inter.event_timestamp,inter_success.event_name
这对于较小的数据集效果很好,但不适用于5900万行...
答案 0 :(得分:2)
TL; DR:您不需要增加BigQuery的内存。
为了回答这个问题,您需要了解BigQuery的工作原理。 BigQuery依赖于称为 slots 的执行器计算机。这些插槽的类型都相似,并且内存量有限。
现在,许多操作将数据拆分到多个插槽之间(例如GROUP BY),每个插槽对一部分数据执行约简操作,然后在执行树中向上发送结果。
某些操作必须在单台计算机上执行(例如SORT和OVER),请参见here。 当数据溢出插槽的内存时,您会遇到上述错误。因此,您真正需要的是将插槽类型更改为更高内存的计算机。不幸的是,这是不可能的。您将必须遵循查询最佳实践,以避免对过多数据进行单插槽操作。
可以帮助您的一件事是使用PARTITIONS计算OVER(),因此每个分区将被发送到不同的计算机。 see this example。通常还可以帮忙的另一件事是,如果您还没有这样做,请转到标准SQL。
答案 1 :(得分:1)
我假设您对子查询使用了with clause,而子查询又耗尽了内存。我建议的解决方案是创建一个过期表,该表将在几天后自动使用
语法过期OPTIONS(expiration_timestamp = TIMESTAMP_ADD(CURRENT_TIMESTAMP(),间隔5天))
通过这种方法,我想将5900万行查询结果行插入到到期表中将使用更少的插槽。将您的后续子查询替换为到期的表名。
为避免为到期表计费,您可以在执行所有相关查询后将其删除。
答案 2 :(得分:0)