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 返回多个值吗?
使用自定义 Python 库 ua-parser 的 Amazon Redshift UDF
Redshift 中的 Python UDF 函数始终返回 NULL 值