使用Google BigQuery上的开始/结束日期优化活动帐户查询

时间:2018-03-16 20:13:11

标签: sql join google-bigquery

我希望优化查询以获得每个时间间隔(日,周等)的活动帐户,其中活动在帐户的开始日期和结束日期定义。布局如下:

accounts: account_id Int subscription_start Timestamp subscription_end Timestamp -- null if still active

我尝试了几种方法,最快的方法是使用generate_array动态创建数组,然后取消它们(约2分钟)

with nested_dates as (
  select GENERATE_DATE_ARRAY(DATE(subscription_start), IFNULL(date(subscription_end), current_date()), INTERVAL 1 DAY) as dates
  from `accounts`
),
all_dates as (
  select date_item from nested_dates, UNNEST(dates) as date_item
)
select date_item, count(1) from all_dates group by date_item

我还使用了每天一个subselect,它曾经在6-9个月之前的类似情况下表现相当不错,当时BigQuery仍然拥有性能层,并且给了CPU更多的lee方式。但现在它们似乎更加严格/效率更低,因为它们取消了更高的计算层价格。这个执行大约需要12分钟。

select
  day,
  (select 
     count(1) 
   from `accounts` where
     subscription_start <= day and 
     (subscription_end is null or subscription_end >= day)
  )
from unnest(
    generate_date_array(date('2015-06-01'), current_date(), interval 1 day)
) AS day

我还对生成日期和条件总和的帐户交叉连接进行了性能测试(由于超出CPU限制,在3300秒后失败)。

当我为每个已激活的帐户生成一个包含所有日期的物化表时,当然我的实施分区可能更快(例如,通过使用来自第一个查询的“all_dates”。

select date(day_active), count(1) from `account_all_dates`

现在的问题是:有没有办法获得物化交叉连接的性能而不先实际耗尽数据并实现它,即实时没有开销。

我正在尝试一些分析功能,但找不到可以做到这一点的东西。

1 个答案:

答案 0 :(得分:4)

我认为您的第一个查询是完美的,是一种方法 它已经是最通用的,适用于任何间隔(日,周等)和所有非物化选项 - 最快的

唯一可能的改进(也有点更紧凑)在下面(在我使用虚拟数据的快速测试中,它总是显示稍快的结果 - 但我不能说这是肯定的 - 看到你的结果会很有趣真实数据)

   
#standardSQL
SELECT date_item, COUNT(1) active_accounts 
FROM `accounts`, 
UNNEST(GENERATE_DATE_ARRAY(DATE(subscription_start), 
  IFNULL(DATE(subscription_end), CURRENT_DATE()), INTERVAL 1 DAY)) date_item
GROUP BY date_item