Эти 3 запроса должны вести себя одинаково (одинаковые результаты и аналогичная производительность), но почему-то NOT IN
и NOT EXISTS
ведут себя намного медленнее.
Я создал ошибку, чтобы отслеживать эту производительностьхит, поскольку он должен быть только временным (https://issuetracker.google.com/issues/116839201).
SELECT tags, COUNT(*) c, ANY_VALUE(b.value)
FROM `bigquery-public-data.stackoverflow.posts_questions` a
LEFT JOIN (SELECT x.value FROM UNNEST((
SELECT APPROX_TOP_COUNT(tags, 10000)
FROM `bigquery-public-data.stackoverflow.posts_questions`
)) x ) b
ON a.tags=b.value
WHERE b.value IS NULL
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1000
12 seconds, fh-bigquery:US.bquijob_3c0fdf82_1661f6f3dd1
SELECT tags, COUNT(*) c
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE tags NOT IN(SELECT x.value FROM UNNEST((
SELECT APPROX_TOP_COUNT(tags, 10000)
FROM `bigquery-public-data.stackoverflow.posts_questions`
)) x)
GROUP BY 1
ORDER BY 2 DESC, 1
LIMIT 1000
> 400 seconds, fh-bigquery:US.bquijob_766cc8ab_1661f7023bb
SELECT tags, COUNT(*) c
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE NOT EXISTS(SELECT x.value FROM UNNEST((
SELECT APPROX_TOP_COUNT(tags, 10000)
FROM `bigquery-public-data.stackoverflow.posts_questions`
)) x WHERE tags=value)
GROUP BY 1
ORDER BY 2 DESC, 1
LIMIT 1000
> 400 seconds, fh-bigquery:US.bquijob_59a9d1e6_1661f59db40
Вообще говоря: NOT EXISTS
должен быть предпочтительнее NOT IN
, так как он ведет себя лучше при нулевых значениях.