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

问题描述

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

当我跑

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行。

标签: pythonamazon-redshiftuser-defined-functions

解决方案



推荐阅读