Redshift Python UDF 自行运行,但在部分使用 count 或作为另一个查询的一部分时会引发错误

Posted

技术标签:

【中文标题】Redshift Python UDF 自行运行,但在部分使用 count 或作为另一个查询的一部分时会引发错误【英文标题】:Redshift Python UDF runs on its own but throws an error when part using count or as part of another query 【发布时间】:2019-08-19 18:20:56 【问题描述】:

编辑/更新(下) 我在 AWS-Redshift 中存储并可以成功运行 python UDF。如果该点在另一个给定点的给定距离内,UDF 将获取纬度/经度点并返回 boolean

当我跑步时

SELECT dist_in_range(5000.0, latitude, longitude, 38.897957, -77.036560) as in_range 
from test_2;

它按预期返回一列真或假。

当我跑步时

SELECT a.in_range from (SELECT dist_in_range(5000.0, latitude, longitude, 38.897957, -77.036560) as in_range 
                             from test_2) as a
                             where a.in_range = false;

过滤假,它再次正确运行。

如果我在查询中添加count() 函数,例如:

SELECT count(a.in_range) from (SELECT dist_in_range(5000.0, latitude, longitude, 38.897957, -77.036560) as in_range 
                             from test_2) as a
                             where a.in_range = false;

它返回错误:

[Amazon](500310) Invalid operation: TypeError: a float is required. Please look at svl_udf_log for more information Details: ----------------------------------------------- error: TypeError: a float is required. Please look at svl_udf_log for more information code: 10000 context: UDF query: 1766 location: udf_client.cpp:369 process: query1_995_1766 [pid=50711] -----------------------------------------------;

此错误似乎表明它是 UDF 和 UDF 输入的问题,但如上所示,UDF 自身正常工作。我认为在结果上使用 count() 只是一个 sql 查询,将返回的项目计数为 false。为什么在尝试计算 UDF 的结果时会出错?

更新/编辑:我开始相信这种类型的精度错误发生在 python 2.7 中(版本 Redshift 文档说明它正在使用)。这是我正在运行的 UDF(感谢 https://skipperkongen.dk/category/spatial/ 获取代码;我只是添加了一些内容):

CREATE OR REPLACE FUNCTION dist_in_range (radius float,lat1 float, lon1 float, lat2 float, lon2 float)
RETURNS bool IMMUTABLE AS
$$

    from math import radians, sin, cos, asin, sqrt, pi, atan2
    import numpy as np

    earth_radius_miles = 3956.0

    def dist_in_range(radius, lat1, lon1, lat2, lon2):
        """checks if a point is within int number of miles of second set of points.
        """
        lat1, lon1 = radians(lat1), radians(lon1)
        lat2, lon2 = radians(lat2), radians(lon2)
        dlat, dlon = float(lat2 - lat1), float(lon2 - lon1)
        a = sin(dlat/2.0)**2 + cos(lat1) * cos(lat2) * sin(dlon/2.0)**2
        great_circle_distance = 2 * asin(min(1,sqrt(a)))
        if float(earth_radius_miles * great_circle_distance) < float(radius):
            return True
        else:
            return False

    return dist_in_range(radius, lat1, lon1, lat2, lon2)
$$ LANGUAGE plpythonu;

在我正在测试的数据集上,如果我运行此查询:

SELECT dist_in_range(40, latitude, longitude, 20.652975, -87.102572) as in_range from test_2
where in_range = true;

它返回没有错误的结果。如果我将半径变量降低到 40 以下,我开始得到“需要浮点数”错误,除非我设置 WHERE in_range = false,然后它再次返回结果而没有错误。

我在 jupyter 笔记本中检查运行较小的半径,在某些情况下,在打印计算步骤时,我得到非常小的数字,例如 1.0134428420666964e-13 所以,我想知道这是 python 2.7 中的精度问题,如果有什么我可以做的调整吗?

最后,aws 错误引用的日志没有提供更多信息,因为它只是模仿“TypeError:需要浮点数”消息,并指向 UDF 中的第 11 行和第 21 行,但第 11 行是注释,第 21 行是 else: return False 行。

【问题讨论】:

Select * from svl_udf_log 的输出是什么?它可能会给你一个提示。 【参考方案1】:

Redshift 现在支持空间数据的 GEOMETRY 数据类型,并拥有 40 多个高性能原生函数。

https://docs.aws.amazon.com/redshift/latest/dg/geospatial-overview.html https://docs.aws.amazon.com/redshift/latest/dg/geospatial-functions.html https://docs.aws.amazon.com/redshift/latest/dg/spatial-limitations.html

【讨论】:

【参考方案2】:

我最初在 Redshift 中使用指定为 NUMERIC 的纬度/经度数据类型创建并加载了具有 (9,6) 精度的表(我已经看到此建议用于处理纬度/经度类型)。我重新加载了表,但将数据类型改为 FLOAT8,现在它工作正常。

我错误地假设小数点后 6 位的数字会被视为浮点数,但事实并非如此。

【讨论】:

以上是关于Redshift Python UDF 自行运行,但在部分使用 count 或作为另一个查询的一部分时会引发错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Redshift 中创建 python UDF 时出错

您可以从 Redshift 中的 python UDF 返回多个值吗?

使用自定义 Python 库 ua-parser 的 Amazon Redshift UDF

Redshift 中的 Python UDF 函数始终返回 NULL 值

如何在 python udf 中使用 select 查询进行 redshift?

在每个函数调用上导入 Redshift Python UDF