Redshift Python UDF导入每个函数调用

时间:2016-08-12 19:29:45

标签: python user-defined-functions amazon-redshift

我开始在Redshift中学习Python用户定义的函数,我有几个问题需要澄清。假设我已经定义了以下函数:

CREATE OR REPLACE FUNCTION f_parse_url_query_string(url VARCHAR(MAX))
RETURNS varchar(max)
STABLE
AS $$
    from urlparse import urlparse, parse_qsl
    import json
    return json.dumps(dict(parse_qsl(urlparse(url)[4])))
$$ LANGUAGE plpythonu;

每次调用该函数时这是运行imports还是由Redshift编译并且只导入一次?

我的第二个问题是是否有办法返回可变数据类型。例如,如果我想创建一个抓取嵌套json字段值的函数,结果可以是从字符串到整数或布尔值的任何内容。有没有在函数返回类型上创建自动检测?

2 个答案:

答案 0 :(得分:1)

<强>执行

是的,import每次都会执行。

避免这种情况的一种方法是使用IMMUTABLE作为函数的波动率。这允许Redshift为给定的输入值缓存​​函数的输出,从而避免将来为相同的输入值运行Python函数。

返回值

返回值的数据类型是固定的,不能更改。可以为不同的函数名称或不同的输入类型定义不同的返回值(例如,定义一个接收的函数)整数并返回一个整数,然后是另一个具有相同名称的函数,但字符串输入类型返回一个字符串作为输出。)

此外,使用返回不同输出数据类型的函数将非常困难 - 调用UDF的SQL语句将需要特定的数据类型,而不是更改的类型。

答案 1 :(得分:1)

<强>进口

是和否。 Redshift在语句中重用udf执行环境(甚至可能在整个事务中,但我还没有测试过)。虽然每次在处理导入语句时调用函数都会处理import语句,但cpython会快速检查模块是否已导入并使用已导入的模块(如果已导入)。像这样的函数本地(后期)导入经常用于解决循环依赖问题,因此必须具有高性能。我也使用它来解决udf中缺少全局初始化的问题,方法如下:

if '_cache' not in globals(): import thing globals()['_cache'] = thing.build_cache() return _cache.get(arg)

除了udf之外,这不是我要做的事情,但这不是通用代码。

关于udf执行环境,它显然是非常详细的,不应过分依赖,但实际上它不太可能很快改变。无法保证任何特定进程的使用寿命/它将处理多少行,但是只要它们可以保持它们,因为cpython进程(和容器)创建并不是很便宜 - 当然每一行都太重了。他们依靠lxc进行隔离,并为您提供一个真正的(如果是沙盒的)Linux环境(如果您考虑的话,这对于用户安装的本机扩展非常必要)。对于那些关心挖掘的人来说,文件系统上甚至还有一些文档:)

返回值

虽然确实无法更改返回值的数据类型,但redshift(now?)支持参数和返回类型的ANYELEMENT数据类型。正如前面的答案所描述的那样,它仍然需要一个消除歧义的类型参数,因为仍然不支持返回类型多态,但它至少可以省去为每个要返回的类型创建单独函数的麻烦。