首页 > 解决方案 > Snowflake UDF 在使用“LIMIT”时表现不同

问题描述

我创建了一个评估行的 UDF。在大多数情况下它工作得很好,但有时它会表现得很奇怪。请参见下面的示例。这些是完全相同的查询。一个有“限制”,另一个没有。这里的总记录数是 32,但我只是为了示例添加了 Limit 1000。您知道为什么这两个查询的行为不同吗?

没有限制 - 错误的输出 在此处输入图像描述

有限制 - 正确输出 - 总记录再次为 32。 在此处输入图像描述

标签: javascriptsnowflake-cloud-data-platform

解决方案


功能代码:

create or replace function new_row_evaluator
       (b varchar, m datetime, f DATETIME, t datetime ) 
returns string
language javascript
as '
if (typeof tmp_barcode === "undefined") {
    tmp_barcode = B;
    tmp_fromdate = F;
    tmp_todate = T;
    return "1";
}
if (tmp_barcode == B) {
    if (M >= tmp_fromdate && M <= tmp_todate) {
        return "0";
    } else {
        tmp_fromdate = F;
        tmp_todate = T;
        return "1";
    }
} else {
    tmp_barcode = B;
    tmp_fromdate = F;
    tmp_todate = T;
    return "1";
} ';

我假设 UDF 正在使用某种全局状态tmp_barcode

全局状态

Snowflake 通常在 UDF 的迭代之间保留 JavaScript 全局状态。但是,您不应依赖先前对函数调用之间可用的全局状态的修改。此外,您不应假定所有行都将在同一个 JavaScript 环境中执行。

推荐的模式是使用 JavaScript 的全局变量语义保证相关代码只被评估一次。例如:

var setup = function() {
/* SETUP LOGIC */
};

if (typeof(setup_done) === "undefined") {
  setup();
  setup_done = true;  // setting global variable to true
}

请注意,此机制仅对缓存代码评估的效果是安全的。不能保证在初始化之后将为所有行保留全局上下文,并且任何业务逻辑都不应该依赖它。


推荐阅读