繁体   English   中英

查询执行期间超出了 Google BigQuery 资源。 如何在 SQL 中拆分带有分区的大 window 帧

[英]Google BigQuery Resources exceeded during query execution. How to split large window frames with partition in SQL

我在 Google BigQuery 上的查询用完了 memory。 我必须计算多个 window 函数,例如在多个不同的时间范围内运行总和。 我的数据主要由一个id(字符串)、一个值(数字)、一个类型('in'或'out',需要可以转换为bool)和一个时间戳组成。

我读到没有办法增加每个槽 memory,所以能够执行查询的唯一方法是将它切成更小的块,可以发送到不同的槽。 一种方法是使用GROUP BYOVER (PARTITION BY...)但我不知道如何重写我的查询以使用它。

我有一些计算需要使用PARTITION BY但对于其他计算,我想计算总计,例如:

想象一下有一个大表(> 10 亿行),我想在其中计算不同时间范围内所有值的滚动总和,与 id 无关。

WITH data AS (
  SELECT * 
  FROM UNNEST([
    STRUCT
    ('A' as id,1 as value, 'out' as type, 1 as time), 
    ('A', -1, 'in', 2),
    ('B', 2, 'out', 2),
    ('C', 1, 'out', 3),
    ('B', -1, 'in', 4),
    ('A', 2, 'out', 4),
    ('C', 5, 'out', 5),
    ('B', 3, 'out', 6),
    ('A', 1, 'out', 6),
    ('A', -4, 'in', 6),
    ('C', -3, 'in', 7)
  ])
)
SELECT 
  id
, value
, type
, time
, SUM(value) OVER (ORDER BY time RANGE UNBOUNDED PRECEDING) as total
, SUM(value) OVER (ORDER BY time RANGE BETWEEN 1 PRECEDING AND CURRENT ROW) as total_last_day
, SUM(value) OVER (ORDER BY time RANGE BETWEEN 3 PRECEDING AND 2 PRECEDING) as total_prev_day
FROM data

我如何拆分此查询以使用PARTITION BYGROUP BY以适应 memory 限制?

尝试以下方法 - 我认为它很有可能解决您的问题

SELECT *
FROM data
JOIN (
  SELECT time
  , SUM(time_value) OVER (ORDER BY time RANGE UNBOUNDED PRECEDING) as total
  , SUM(time_value) OVER (ORDER BY time RANGE BETWEEN 1 PRECEDING AND CURRENT ROW) as total_last_day
  , SUM(time_value) OVER (ORDER BY time RANGE BETWEEN 3 PRECEDING AND 2 PRECEDING) as total_prev_day
  FROM (
    SELECT time, SUM(value) time_value
    FROM data
    GROUP BY time
  )
)
USING (time)       

如果应用于您问题中的示例数据 - output 是

在此处输入图像描述

Window 特殊排序的函数 partition by etc 通常非常重,在大数据上使用它可能需要很长时间。

看起来您的预期结果是在您的示例查询中键入您的 id。

您可以检查以下几项:

查看您的源数据是否可以按 id 进行“聚类”,这样处理开始时会更快。

如果这不起作用,请查看添加以下样式的过滤器是否有效:

select ...
where mod(farm_fingerprint(id), 5) = 0

将它存储在一个表中,并继续将下一个 mods(=1 到 4)附加到该表。 "%5=0" mod 作为示例给出,您必须在知道源数据的情况下对其进行试验。 此处使用 mod 会将您的源数据拆分为 5 个较小的存储桶以供使用,因此您稍后必须将其全部 append。 这样 BQ 内部 memory 所需的数据量将会减少,并且它可能会在其限制范围内处理结果。

如果上述任何想法可行,您都可以在 sql 脚本中执行此操作,这样您就可以创建临时表并使用它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM