如何在 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_4000
、mydataset.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 数据转换的强大功能!我仍然认为(但我可能是错的)存储物化特征矩阵不是最好的主意
比方说,我有给定日期的音乐视频播放统计数据 table mydataset.stats(3B 行,100 万用户,6000 位艺术家)。 简化架构是: UserGUID 字符串、ArtistGUID 字符串
我需要从行到列的 pivot/transpose 位艺术家,因此架构将是:
UserGUID 字符串、Artist1 Int、Artist2 Int、... Artist8000 Int
各个用户的艺术家播放次数
我的示例可以扩展此方法吗?
我针对多达 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_4000
、mydataset.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 数据转换的强大功能!我仍然认为(但我可能是错的)存储物化特征矩阵不是最好的主意