问题描述
给定约2300万用户,计算给定一天(即使未执行任何登录)在最近X个月内的累计登录数的最有效方法是什么?客户的开始日期是其首次登录,结束日期是今天。
所需的输出
c_id day nb_logins_past_6_months
----------------------------------------------
1 2019-01-01 10
1 2019-01-02 10
1 2019-01-03 9
...
1 today 5
➔每位用户每天一行,包含当前日期和过去179天之间的登录次数
方法1
1. Cross join each customer ID with calendar table
2. Left join on login table on day
3. Compute window function (i.e. `sum(nb_logins) over (partition by c_id order by day rows between 179 preceding and current row)`)
+ Easy to understand and mantain
- Really heavy,quite impossible to run on daily basis
- Incremental does not bring much benefit : still have to go 179 days in the past
方法2
1. Cross join each customer ID with calendar table
2. Left join on login table on day between today and 179 days in the past
3. Group by customer ID and day to get nb logins within 179 days
+ Easier to do incremental
- Table at step 2 is exceeding 300 billion rows
知道这不是唯一的用例时,通常的处理方法是什么,我们必须计算其他类似的列(过去12个月中的nb次登录等)
解决方法
在标准SQL中,您将使用:
select l.*,count(*) over (partition by customerid
order by login_date
range between interval '6 month' preceding and current row
) as num_logins_180day
from logins l;
这假设logins
表的登录日期没有时间成分。
我认为没有理由将2300万用户乘以180天来生成超过400万行的结果集来回答这个问题。
,为了提高性能,请不要一次完成全部任务。取而代之的是,在每个月末(或一天或对您的数据有意义的任何事情)收集小计。然后2^32
向上分类汇总以提供“报告”。
更多讨论(重点是MySQL):http://mysql.rjweb.org/doc.php/summarytables
(您应该使用特定产品标记问题;不同的产品具有不同的语法/功能/性能等)