我有一张表格,内容如下:
- 表尺寸39.6 MB
- 行数691,562
- 2列:contact_guid STRING,program_completed STRING
- 第1列数据类型与uuid类似。大约30个字符长度
- 第2列数据类型是大约50个字符长度的字符串
我正在尝试此查询:
#standardSQL
SELECT
cp1.contact_guid AS p1,
cp2.contact_guid AS p2,
COUNT(*) AS cnt
FROM
`data.contact_pairs_program_together` cp1
JOIN
`data.contact_pairs_program_together` cp2
ON
cp1.program_completed=cp2.program_completed
WHERE
cp1.contact_guid < cp2.contact_guid
GROUP BY
cp1.contact_guid,
cp2.contact_guid having cnt >1 order by cnt desc
执行时间:1200秒
我知道我正在进行自我加入,并且在最佳做法中提到了避免自我加入。
我的问题:
答案 0 :(得分:1)
如您提供的屏幕截图所示 - 您正在处理爆炸式连接。
在这种情况下,第3步需要130万行,并且可以产生4.59亿行。步骤04到0B处理所有额外数据的重新分区和重新洗牌 - 因为查询没有提供足够的资源来处理这些行数:它从1个并行输入扩展到10,000个!
这里有两个选择:要么避免爆炸连接,要么假设爆炸连接需要很长时间才能运行。但正如问题中所解释的那样 - 你已经知道了!
如果在一个op中生成所有额外的行(执行join,materialize)然后运行另一个查询来处理459万行,该怎么办?由于解释的原因,第一个查询会很慢,但第二个查询会很快运行,因为BigQuery会提供足够的资源来处理这些数据。
答案 1 :(得分:0)
同意以下建议
看看你是否可以使用分析函数(由Tim)重新编写查询
使用分析函数会更好(Elliott)
以下是我如何制作
#standardSQL
SELECT
p1, p2, COUNT(1) AS cnt
FROM (
SELECT
contact_guid AS p1,
ARRAY_AGG(contact_guid) OVER(my_win) guids
FROM `data.contact_pairs_program_together`
WINDOW my_win AS (
PARTITION BY program_completed
ORDER BY contact_guid DESC
RANGE BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
)
), UNNEST(guids) p2
GROUP BY p1, p2
HAVING cnt > 1
ORDER BY cnt DESC
如果有帮助,请尝试通知我们