【问题标题】:BigQuery - using SQL UDF in join predicateBigQuery - 在连接谓词中使用 SQL UDF
【发布时间】:2019-07-19 17:14:27
【问题描述】:

我在运行左连接时尝试使用 SQL UDF,但收到以下错误:

连接谓词中的子查询应该只依赖于一个连接端。

查询是:

CREATE TEMPORARY FUNCTION game_match(game1 STRING,game2 STRING) AS (
  strpos(game1,game2) >0
);

SELECT 
  t1.gameId 
  FROM `bigquery-public-data.baseball.games_post_wide` t1
  left join `bigquery-public-data.baseball.games_post_wide` t2 on t1.gameId=t2.gameId and game_match(t1. gameId, t2.gameId)

在内联编写条件时,查询有效,而不是函数调用(strpos(t1. gameId, t2. gameId) >0)

此特定函数是否存在问题,或者连接谓词通常不支持 SQL UDF(出于某种原因)?

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    您可以在the issue tracker 上提交功能请求以完成这项工作。这是查询计划/优化的限制;对于某些背景,BigQuery 会转换函数调用,以便查询的逻辑表示如下:

    SELECT 
      t1.gameId 
    FROM `bigquery-public-data.baseball.games_post_wide` t1
    left join `bigquery-public-data.baseball.games_post_wide` t2
    on t1.gameId=t2.gameId
      and (SELECT strpos(game1,game2) > 0 FROM (SELECT t1.gameId AS game1, t2.gameId AS game2))
    

    BigQuery 像这样转换 SQL UDF 调用的原因是它需要避免多次计算输入。虽然在这种特殊情况下这不是问题,但如果您在 UDF 正文中多次引用其中一个输入,例如考虑这个 UDF:

    CREATE TEMP FUNCTION Foo(x FLOAT64) AS (x - x);
    SELECT Foo(RAND());
    

    如果 BigQuery 直接内联表达式,您将得到以下结果:

    SELECT RAND() - RAND();
    

    结果不会为零,考虑到 UDF 的定义,这是出乎意料的。

    在大多数情况下,BigQuery 的逻辑优化将如上所示的更复杂的子选择转换为更简单的形式,假设这样做不会改变查询的语义。但是,在这种情况下并没有发生这种情况,因此出现了错误。

    【讨论】:

    • “连接谓词中的子查询应该只依赖于一个连接侧”的限制背后的原因是什么?
    • 如果条件是子查询而不是相等条件,BigQuery 无法有效地并行化联接,并且更愿意返回错误而不是非常缓慢地执行查询。
    • 所以如果我需要做这样的事情,我应该把 UDF 调用移到 WHERE 子句中?
    猜你喜欢
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多