为什么BigQuery不优化LEFT JOIN和GROUP BY

时间:2018-02-20 20:44:03

标签: sql google-cloud-platform google-bigquery standard-sql

我有以下查询:

#standardSQL

WITH users AS (
  SELECT 1 id, 'pieter' name UNION ALL
  SELECT 2   , 'george'      UNION ALL
  SELECT 3   , 'maggie'
),
invoices AS (
  SELECT 1 id, 1 userId, 25.0 amount, 'taxi fee' description UNION ALL
  SELECT 2   , 1       , 300.0      , 'conference ticket'    UNION ALL
  SELECT 3   , 1       , 300.0      , 'hotel room'           UNION ALL
  SELECT 5   , 3       , 70         , 'airbnb'               UNION ALL
  SELECT 6   , 3       , 22         , 'concert ticket'
)
SELECT
  users.id userId,
  users.name userName
FROM 
  users
LEFT JOIN 
  invoices ON invoices.userId = users.id
GROUP BY
  users.id,
  users.name
ORDER BY
  users.id

在这种情况下,查询处理器可以轻松地优化(省略)LEFT JOIN和GROUP BY的组合。但是当我查看查询计划时,BigQuery仍然会执行连接。为什么?我怎样才能避免这种行为?

我的用例:我有一个视图,其中包含一些需要此类连接的字段。我不想在没有查询字段时执行连接。

我使用standardSQL方言。

1 个答案:

答案 0 :(得分:3)

让我详细说明我的评论。

您可能不理解查询可以执行的所有不同方式。让我走出BQ(我对此有所了解,但肯定缺乏深入的知识),并指出一些用于加入和聚合的算法:

  • join:嵌套循环
  • join:在一个表上使用索引的嵌套循环
  • join:index merge
  • join:sort and merge
  • join:hash and match,with memory and out-of-memory variants
  • 聚合:基于哈希的
  • 聚合:基于排序的
  • 聚合:基于索引的
  • 以上所有的并行版本

我意识到基于索引的方法不适用于BQ。但这些都是为了给你一种味道。然后,在选择特定算法后,可能仍然存在参数和子方法 - 使用什么类型的算法?哈希表有多大?如何处理碰撞?关于并行性和偏斜,BQ有自己需要设置的参数。

这些是优化器解决的难题。写这些的人每天都来上班(也许是远程)。他们有一个选择:

  • 我是否想要修复写得不好的查询,而作者应该知道如何更好地编写它?
  • 我是否想要找出可能影响所有用户的一般查询类的最佳算法和实现?

编辑:

在评论中,OP指出他/她实际上指的是视图。这是一个完全不同的动物,在这种情况下,联合消除是一种非常合理的优化策略。