【问题标题】:How to scale Pivoting in BigQuery?如何在 BigQuery 中扩展 Pivoting?
【发布时间】:2016-04-23 02:11:03
【问题描述】:

假设我有给定日期的音乐视频播放统计表 mydataset.stats(3B 行,100 万用户,6K 艺术家)。 简化的架构是: UserGUID 字符串、ArtistGUID 字符串

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

How to transpose rows to columns with large amount of the data in BigQuery/SQL?How to create dummy variable columns for thousands of categories in Google BigQuery? 中提出了一种方法,但看起来它不适用于我的示例中的数字

可以为我的示例扩展这种方法吗?

【问题讨论】:

    标签: sql google-bigquery


    【解决方案1】:

    我尝试了以下方法来处理多达 6000 个功能,它按预期工作。我相信它最多可以使用 10K 功能,这是表中列数的硬性限制

    第 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)拥有更多可用/友好的列名

    结合第一步——它将是:

    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 
    

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

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

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

    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 &gt; NNNN and aid &lt; NNNN)我们得到三个表mydataset.pivot_2001_4000mydataset.pivot_4001_6000
    如您所见 - mydataset.pivot_1_2000 具有预期的模式,但对于从 1 到 2001 的辅助功能; mydataset.pivot_2001_4000 仅具有从 2001 到 4000 的辅助功能;等等

    第 4 步 – 将所有分区数据透视表合并到最终数据透视表中,所有特征都表示为一个表中的列

    与上述步骤相同。首先我们需要生成查询然后运行它 因此,最初我们将“缝合”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

    结果表具有以下架构:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 2016-07-17
      相关资源
      最近更新 更多