让我们说,我有一天的音乐视频播放统计表mydataset.stats(3B行,1M用户,6K艺术家)。 简化的架构是: UserGUID String,ArtistGUID String
我需要从行到列的透视/转置艺术家,因此架构将是:
UserGUID String,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?中建议采用的方法,但看起来它不能扩展我的示例中的数字
这种方法可以缩放我的例子吗?
答案 0 :(得分:8)
我尝试了以下方法,最多可以使用6000个功能,并且按预期工作。我相信它最多可以使用10K功能,这是表格中列数的硬限制
第1步 - 按用户/艺术家进行汇总
SELECT userGUID as uid, artistGUID as aid, COUNT(1) as plays
FROM [mydataset.stats] GROUP BY 1, 2
第2步 - 规范化uid和辅助 - 因此它们是连续的数字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 > NNNN and aid < NNNN
)我们又增加了三个表mydataset.pivot_2001_4000
,mydataset.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'/ strong>即可。步骤3和4中第二次/主要查询的运行时间从20到60分钟不等
<强> C 即可。重要提示:步骤3和4中的计费层从1到90不等。好消息是各个表的大小相对较小(30-40MB),因此计费字节也是如此。对于“2016年之前”项目,所有项目都被计为第1级,但在2016年10月之后,这可能是一个问题
有关详细信息,请参阅High-Compute queries中的Timing
的 d 即可。以上示例显示了使用BigQuery进行大规模数据转换的强大功能!我认为(但我可能错了)存储物化特征矩阵不是最好的想法