【问题标题】:BigQuery user-defined function in JavaScript does not prune partitionsJavaScript 中的 BigQuery 用户定义函数不会修剪分区
【发布时间】:2021-12-11 11:50:15
【问题描述】:

我有一个 BigQuery 表,我想按低基数字符串列进行分区。这是不可能的,所以我必须将字符串散列成整数并按整数分区。我做了一个非常简单的散列算法,将这些字符串转换为 0 到 100 之间的整数。

到目前为止一切顺利,我创建了一个由这个新整数字段分区的新表,它只是另一个字段的函数。现在我可以通过分区整数字段查询这张表,大大减少了流量。凉爽的!但我真的很想通过字符串字段查询,所以我做了一个用户定义的函数,它基本上是做散列的,所以我可以写这样的查询:

SELECT * FROM `partitioned_table` WHERE partitioned_int_field = HashOf("abc")

与此基本相同,但性能更高:

SELECT * FROM `partitioned_table` WHERE unpartitioned_string_field = "abc"

现在的问题是,如果我将用户定义的函数 HashOf 创建为 SQL(例如,只是幼稚的情况)它工作得很好,流量会按预期减少。但是,如果我将函数创建为 JavaScript(这里更可取),那么它对流量没有影响。查询有效,但需要全表扫描。 SQL 和 JavaScript 版本都返回完全相同的结果,但 JavaScript 版本并没有像看起来那样修剪分区。

我错过了什么吗?为什么 JavaScript 用户定义函数即使为分区字段返回正确的整数值,也不修剪分区?

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    您必须分两步执行查询:

    • 首先,计算哈希字段
    • 二、用计算字段查询分区表

    类似的东西

    DECLARE hhh INT64;
    
    CREATE TEMP FUNCTION getHash()
    RETURNS INT64
    LANGUAGE js AS r"""
      return 1;
    """;
    
    set hhh = (select getHash());
    
    SELECT * FROM `gdglyon-cloudrun.dlp_test.number_partitioned` where num_partition=hhh;
    

    它应该可以工作。

    【讨论】:

    • 没有帮助。它的工作方式完全相同:全扫描,不进行分区修剪
    • 我进行了测试,如果使用 UDF,with 在没有函数的情况下效果很好,但会失败(实际上是执行完整扫描)。我用脚本成功地完成了这一点(在我的答案中更新了
    • DECLARE 一起工作。尽管可用性受到影响。这是设计使然还是某些极端情况?我的意思是直接在查询中调用 UDF
    • 同意,可用性很差,但是当您了解 BigQuery 的设计时,这是可以理解的:它可以在查询运行之前猜测要加载的分区是什么。因为 BigQuery 需要运行查询来解释 UDF 并获取该值。所以,它加载所有 -> 全扫描
    猜你喜欢
    • 1970-01-01
    • 2023-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2017-12-03
    相关资源
    最近更新 更多