加入与子查询
Posted
技术标签:
【中文标题】加入与子查询【英文标题】:Join vs. Subquery 【发布时间】:2017-08-02 17:01:30 【问题描述】:我在资源和性能方面一直在寻找联接与子查询,答案似乎取决于平台。但就 BigQuery 而言,似乎没有人谈论它们。
当我将查询范围扩大到 100 GB 时,我遇到了一个
Query Failed
Error: Resources exceeded during query execution.
我大概有
#standardSQL
SELECT * FROM table t1 WHERE
(t1.a in (SELECT b FROM anothertable WHERE class='value')
OR t1.a in (SELECT c FROM table2) )
我想知道在 BigQuery 中 JOIN 是否会更好,尤其是当我扩展到 TB 的数据时。
【问题讨论】:
为什么不实际尝试 JOIN 并分享结果 :o) 或者尝试EXISTS
而不是IN
,因为由于空处理,语义和执行略有不同。
@MikhailBerlyant 如果以前没有人做过,我会这样做,但我需要很长时间才能弄清楚如何更改语义。
如果您是初学者并且在使用连接构建查询时需要帮助 - 只需提出特定问题 :o) 您当前的问题(即 - 我想知道在 BigQuery 中连接是否会更好,特别是如果我扩展到 TB 的数据。)太笼统了
@ElliottBrossard 如果EXISTS
与IN
不同,除非我执行EXISTS (SELECT c FROM table2 WHERE t1.a=c)
之类的操作。为什么 null 处理很重要?
【参考方案1】:
注意这个查询和下一个查询的区别:
1)
#standardSQL
SELECT COUNTIF(author IN (
SELECT author
FROM `fh-bigquery.reddit_comments.2017_01`
))
FROM `fh-bigquery.reddit_comments.2017_01`
2)
#standardSQL
SELECT COUNTIF(author IN (
SELECT DISTINCT author
FROM `fh-bigquery.reddit_comments.2017_01`
))
FROM `fh-bigquery.reddit_comments.2017_01`
这是一个愚蠢的查询 - 两者都应该返回 157893170
。尽管如此,1) 已经运行了超过 8 分钟(到目前为止),而 2) 运行了 36 秒。
秘诀?在执行IN()
时,请确保使用DISTINCT
删除重复项 - 如果没有,将有很多行要 JOIN 根本不会改变结果。
// TODO(gcp): This could be a BigQuery optimization.
【讨论】:
这是一个有趣的发现,但我仍然遇到同样的错误,主要是因为我的子查询已经查询了应该承载大部分不同行的表。 这些表有多大?您可以从这些表中执行 SELECT COUNT(DISTINCT) 吗?也许 OR 正在抛弃它 - 如果您将 2 个表合并,这样 IN 只在一个列表上运行一次呢? 大约 45000 与所有 or 语句不同。我将看到联合如何改变任何东西,尽管我只是认为资源爆炸与 SELECT 的主查询有关。我稍后会在 UNION 上发布。 而 UNION 也让资源消耗殆尽。【参考方案2】:我想知道,您是否尝试过 Elliott 使用 EXISTS
的建议?
类似:
WITH table1 AS(
SELECT '1' as user, 1 AS id UNION ALL
SELECT '2' AS user, 2 as id UNION ALL
SELECT '3' AS user, 3 as id
),
anothertable AS(
SELECT '1' AS user, 'value' AS class , '4' AS c UNION ALL
SELECT '2' AS user, 'value2' AS class, '2' AS c UNION ALL
SELECT '4' AS user, 'value' AS class, '3' AS c UNION ALL
SELECT '5' AS user, 'value2' AS class, '5' as c
),
table2 AS(
SELECT '4' AS c UNION ALL
SELECT '2' AS c UNION ALL
SELECT '3' AS c UNION ALL
SELECT '5' as c
)
SELECT
t1.*
FROM table1 t1
WHERE TRUE
AND EXISTS(SELECT 1 FROM anothertable ta WHERE (class = 'value' AND t1.user = ta.user))
OR EXISTS(SELECT 1 FROM table2 t2 WHERE t1.user = t2.c)
是否超出资源?
【讨论】:
来自 BigQuery,我得到Error: Correlated subqueries that reference other tables are not supported unless they can be de-correlated, such as by transforming them into an efficient JOIN.
以上是关于加入与子查询的主要内容,如果未能解决你的问题,请参考以下文章