JavaScript 中的 BigQuery 用户定义函数不会修剪分区

Posted

技术标签:

【中文标题】JavaScript 中的 BigQuery 用户定义函数不会修剪分区【英文标题】:BigQuery user-defined function in JavaScript does not prune partitions 【发布时间】: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 用户定义函数即使为分区字段返回正确的整数值,也不修剪分区?

【问题讨论】:

【参考方案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 并获取该值。所以,它加载所有 -> 全扫描

以上是关于JavaScript 中的 BigQuery 用户定义函数不会修剪分区的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 是不是支持分析用户定义的函数?

如何为 Google BigQuery 转义 JavaScript UDF 中的字符?

BigQuery JavaScript UDF 使用 SQL 查询中的值调用数组

如何从 BigQuery JavaScript UDF 为字符串化几何集合中的每个要素创建几何?

如何从 BigQuery 中的 Firebase 事件中获取用户表?

在 mapreduce 中实现 BigQuery UDF 作为地图的动机是啥?