如何在 BigQuery 中扩展 Pivoting?

How to scale Pivoting in BigQuery?

比方说,我有给定日期的音乐视频播放统计数据 table mydataset.stats(3B 行,100 万用户,6000 位艺术家)。 简化架构是: UserGUID 字符串、ArtistGUID 字符串

我需要从行到列的 pivot/transpose 位艺术家,因此架构将是:
UserGUID 字符串、Artist1 Int、Artist2 Int、... Artist8000 Int
各个用户的艺术家播放次数

and How to create dummy variable columns for thousands of categories in Google BigQuery? 中建议了一种方法,但它似乎无法扩展到我示例中的数字

我的示例可以扩展此方法吗?

我针对多达 6000 个特征尝试了以下方法,它按预期工作。我相信它最多可以使用 10K 个功能,这是 table

中列数的硬性限制

第 1 步 - 按用户/艺术家汇总播放

SELECT userGUID as uid, artistGUID as aid, COUNT(1) as plays 
FROM [mydataset.stats] GROUP BY 1, 2

第 2 步 – 规范化 uid 和 aid – 因此它们是连续的数字 1, 2, 3, … .
我们至少需要这样做有两个原因:a) 使以后动态创建的 sql 尽可能紧凑和 b) 有更多 usable/friendly 列名称

结合第一步——它将是:

SELECT u.uid AS uid, a.aid AS aid, plays 
FROM (
  SELECT userGUID, artistGUID, COUNT(1) AS plays 
  FROM [mydataset.stats] 
  GROUP BY 1, 2
) AS s
JOIN (
  SELECT userGUID, ROW_NUMBER() OVER() AS uid FROM [mydataset.stats] GROUP BY 1
) AS u ON u. userGUID = s.userGUID
JOIN (
  SELECT artistGUID, ROW_NUMBER() OVER() AS aid FROM [mydataset.stats] GROUP BY 1
) AS a ON a.artistGUID = s.artistGUID 

让我们将输出写入 table - mydataset.aggs

第 3 步 – 一次对 N 个特征(艺术家)使用已经建议的(在上述问题中)方法。 在我的特定示例中,通过实验,我发现基本方法适用于 2000 到 3000 之间的特征数量。 为了安全起见,我决定一次使用 2000 个功能

以下脚本用于动态生成查询,然后 运行 创建分区 tables

SELECT 'SELECT uid,' + 
   GROUP_CONCAT_UNQUOTED(
      'SUM(IF(aid=' + STRING(aid) + ',plays,NULL)) as a' + STRING(aid) 
   ) 
   + ' FROM [mydataset.aggs] GROUP EACH BY uid'
FROM (SELECT aid FROM [mydataset.aggs] GROUP BY aid HAVING aid > 0 and aid < 2001)

上面的查询产生另一个如下查询:

SELECT uid,SUM(IF(aid=1,plays,NULL)) a1,SUM(IF(aid=3,plays,NULL)) a3,
  SUM(IF(aid=2,plays,NULL)) a2,SUM(IF(aid=4,plays,NULL)) a4 . . .
FROM [mydataset.aggs] GROUP EACH BY uid 

这应该是 运行 并写入 mydataset.pivot_1_2000

再执行 STEP 3 两次(调整 HAVING aid > NNNN and aid < NNNN)我们又得到三个 tables mydataset.pivot_2001_4000mydataset.pivot_4001_6000
如您所见 - mydataset.pivot_1_2000 具有预期的架构,但具有从 1 到 2001 的辅助功能; mydataset.pivot_2001_4000 只有从 2001 年到 4000 年的援助特征;等等

第 4 步 – 将所有分区枢轴 table 合并到最终枢轴 table,所有特征都表示为一个 table[= 中的列25=]

与上述步骤相同。首先我们需要生成查询然后 运行 它 因此,最初我们将“拼接”mydataset.pivot_1_2000 和 mydataset.pivot_2001_4000。然后用 mydataset.pivot_4001_6000

结果
SELECT 'SELECT x.uid uid,' + 
   GROUP_CONCAT_UNQUOTED(
      'a' + STRING(aid) 
   ) 
   + ' FROM [mydataset.pivot_1_2000] AS x
JOIN EACH [mydataset.pivot_2001_4000] AS y ON y.uid = x.uid
'
FROM (SELECT aid FROM [mydataset.aggs] GROUP BY aid HAVING aid < 4001 ORDER BY aid)

上面的输出字符串应该是 运行 并且结果写入 mydataset.pivot_1_4000

然后我们重复下面的步骤 4

SELECT 'SELECT x.uid uid,' + 
   GROUP_CONCAT_UNQUOTED(
      'a' + STRING(aid) 
   ) 
   + ' FROM [mydataset.pivot_1_4000] AS x
JOIN EACH [mydataset.pivot_4001_6000] AS y ON y.uid = x.uid
'
FROM (SELECT aid FROM [mydataset.aggs] GROUP BY aid HAVING aid < 6001 ORDER BY aid)

要写入的结果 mydataset.pivot_1_6000

结果 table 具有以下架构:

uid int, a1 int, a2 int, a3 int, . . . , a5999 int, a6000 int 

注意:
一个。我只尝试了这种方法最多 6000 个特征并且它按预期工作
b。 运行 第 3 步和第 4 步中 second/main 查询的时间从 20 分钟到 60 分钟不等
c。重要提示:步骤 3 和 4 中的计费等级从 1 到 90 不等。好消息是相应的 table 的大小相对较小 (30-40MB),计费字节也是如此。对于“2016 年之前”的项目,所有项目都按 1 级计费,但在 2016 年 10 月之后,这可能是一个问题。
有关详细信息,请参阅 High-Compute queries
中的 Timing d。上面的示例展示了使用 BigQuery 进行 large-scale 数据转换的强大功能!我仍然认为(但我可能是错的)存储物化特征矩阵不是最好的主意