はじめに
RedshiftのUDFをLambdaで実装できるようになったとのことで、開発ガイドのCREATE EXTERNAL FUNCTIONに載っているサンプルで試してみました。(「Python Lambda 関数を使用したスカラー Lambda UDF の例」)
事前準備
IAMロール作成&Redshiftクラスタ作成
(正直IAMロール系はあまり詳しくなく)「AWSLambdaRole」を付けたRedshift用ロールを作ってRedshiftクラスターを作成。
Lambda関数作成
ファンクション名:「lambda_multiplication」
ランタイム:「Python 3.8」
コード↓
import json
def lambda_handler(event, context):
t1 = event['arguments']
resp = [None]*len(t1)
success = True
for i, x in enumerate(t1):
mul = 1
for j, y in enumerate(x):
mul = mul*y
if (mul >= 9223372036854775807 or mul <= -9223372036854775808):
success = False
break
else:
resp[i] = mul
ret = dict()
ret['success'] = success
if not success:
ret['error_msg'] = "Integer multiplication overflow"
else:
ret['results'] = resp
ret_json = json.dumps(ret)
return ret_json
Lambdaをテストするなら下記をテストイベントにセット
テストイベント
{
"arguments": [[ 1, 2, 3 ]]
}
UDF作成
UDF作成
CREATE EXTERNAL FUNCTION exfunc_multiplication2(int, int, int)
RETURNS INT
STABLE
LAMBDA 'lambda_multiplication'
IAM_ROLE '(作成したIAMロールのarn)';
UDF実行
テーブル作成&レコード投入
dev=# CREATE TABLE t_multi (c1 int, c2 int, c3 int);
dev=# INSERT INTO t_multi VALUES (1, 2, 3);
UDF実行
dev=# SELECT c1,c2,c3,exfunc_multiplication(c1, c2, c3) FROM t_multi;
c1 | c2 | c3 | exfunc_multiplication2
----+----+----+------------------------
1 | 2 | 3 | 6
(1 row)
RedshiftからLambdaに渡されるeventメッセージ
クエリidもわかるのはいいですね。
{
'user': 'postgres01',
'cluster': '(redshiftクラスターのarn)',
'database': 'dev',
'external_function': 'exfunc_multiplication',
'query_id': 971,
'request_id': 'b314ebaf-1536-4516-94bf-0df6fa354efd',
'arguments': [[1, 2, 3]],
'num_records': 1
}
ちなみにテーブルに複数レコードある場合は下記のようになります。
おそらく一定のバルクでレコードをLambda側に渡してるものと思われます。
{
'user': 'postgres01',
'cluster': '(redshiftクラスターのarn)',
'database': 'dev',
'external_function': 'exfunc_multiplication',
'query_id': 1035,
'request_id': 'efa5334f-6512-4967-bfc8-3f2131a71782',
'arguments': [[1, 2, 3], [2, 3, 4]],
'num_records': 2
}
ちなみに
Explain上もほんの少しcostが変わりました。
{
dev=# EXPLAIN SELECT c1,c2,c3,exfunc_multiplication(c1, c2, c3) FROM t_multi;
QUERY PLAN
-----------------------------------------------------------
XN Seq Scan on t_multi (cost=0.00..0.03 rows=2 width=12)
(1 row)
dev=#
dev=# EXPLAIN SELECT c1,c2,c3 FROM t_multi;
QUERY PLAN
-----------------------------------------------------------
XN Seq Scan on t_multi (cost=0.00..0.02 rows=2 width=12)
(1 row)
さいごに
細やかなことができるのはいいですが、やはり気になるのはパフォーマンスですよね。。
今後試してみようと思います。