PolarDB-X のユーザー定義関数 (UDF) は、カスタム計算でクエリロジックを拡張する SQLベースのストアドファンクションです。
UDF は PolarDB-X 5.4.16 以降でサポートされています。
仕組み

UDF を作成すると、PolarDB-X はそれをメタセンターに永続化し、実行のためにコンピューティングノードにロードします。実行はロジックタイプによって分割されます。
SQLロジック — SQLエンジンに送信されます
制御フローロジック — PLエンジンで実行されます
実行前に、各 UDF はランタイム関数管理センターに登録されます。クエリごとのメモリ使用量は、実行中に厳しく制限されます。
関数プッシュダウン
PolarDB-X は、UDF の SQL DATA ACCESS フィールドをチェックして、データノードに登録するかどうかを決定します。SQL DATA ACCESS が NO SQL に設定されている UDF のみがデータノードに登録され、プッシュダウンできます。
MySQL互換性を維持するため、PolarDB-X はプッシュダウン可能な UDF をデータノード上の MySQLライブラリに登録します。
UDF のプッシュダウンロジックが関係しているため、SQL DATA ACCESS フィールドは変更できません。スケーリング後のプッシュダウン
スケーリング後、pushdown udf を実行して、プッシュダウン可能な UDF を新しいデータノード (DN) に登録します。
MySQLとの相違点
PolarDB-X UDF は、MySQLストアドファンクションと次の3つの点で異なります。
| 相違点 | MySQL | PolarDB-X |
|---|---|---|
| サポートされる操作 | DQL, DML, DDL | DQLのみ — UDF 内では DML および DDL はサポートされません |
| ストレージスコープ | データベースレベル | インスタンスレベル |
SQL DATA ACCESS フィールド | ALTER FUNCTION | 変更不可 — プッシュダウン動作を制御します |
構文
UDFの作成
CREATE
[DEFINER = user]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
func_parameter:
param_name type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement主な特性:
| 特性 | 説明 |
|---|---|
[NOT] DETERMINISTIC | 関数が決定論的であることを示します。同じ入力は常に同じ出力を返します。DETERMINISTIC を使用して最適化を許可します。 |
NO SQL | CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA | SQL DATA ACCESS フィールドを設定します。NO SQL に設定すると、データノードへのプッシュダウンが有効になります。このフィールドは作成後に変更できません。 |
SQL SECURITY DEFINER | INVOKER | 関数が関数作成者 (DEFINER) または呼び出し元 (INVOKER) の権限で実行されるかどうかを決定します。 |
例:
CREATE FUNCTION my_mul(x int, y int)
RETURNS int
LANGUAGE SQL
DETERMINISTIC
COMMENT 'my multiply function'
RETURN x*y*31;UDFの呼び出し
UDF はビルトイン関数と同じ方法で呼び出します。
SELECT my_mul(2, 2);
+--------------+
| my_mul(2, 2) |
+--------------+
| 124 |
+--------------+UDFの変更
ALTER FUNCTION は COMMENT、LANGUAGE SQL、および SQL SECURITY の変更をサポートします。SQL DATA ACCESS の変更はサポートしていません。
ALTER FUNCTION func_name [characteristic ...]
characteristic: {
COMMENT 'string'
| LANGUAGE SQL
| SQL SECURITY { DEFINER | INVOKER }
}UDFの削除
DROP FUNCTION [IF EXISTS] FUNCTION_NAME;UDFの表示
すべての UDF の表示:
SELECT * FROM information_schema.Routines WHERE ROUTINE_TYPE = 'FUNCTION';特定の UDF の表示:
SHOW FUNCTION STATUS [LIKE 'pattern' | WHERE expr]
SHOW CREATE FUNCTION function_name;
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME = 'function_name';プッシュダウンされた UDF の表示:
SELECT * FROM information_schema.pushed_function;実行中の UDF のキャンセル
UDF を実行しているクエリを終了するには、KILL 文を実行します。
KILL {QUERY | CONNECTION} connection_id;キャッシュ管理
UDF メタデータ (関数が存在するかどうか) は常にキャッシュに存在します。関数本体は、最初に呼び出されたときにのみオンデマンドでロードされます。
キャッシュコマンド
| コマンド | 説明 |
|---|---|
SELECT * FROM information_schema.function_cache; | キャッシュされた UDF とそのロードされたサイズを表示します |
SELECT * FROM information_schema.function_cache_capacity; | ノードごとの使用済みおよび合計キャッシュサイズを表示します |
RESIZE FUNCTION CACHE num; | キャッシュサイズを設定します |
CLEAR FUNCTION CACHE; | キャッシュをクリアします |
RELOAD FUNCTIONS; | すべての UDF を再ロードし、キャッシュをリセットします |
キャッシュライフサイクルの例
次の例は、my_mul の完全なキャッシュライフサイクルを説明します。
-- Create the UDF.
CREATE FUNCTION my_mul(x int, y int)
RETURNS int
LANGUAGE SQL
DETERMINISTIC
COMMENT 'my multiply function'
RETURN x*y*31;
-- The function exists in cache, but the body is not loaded yet (SIZE = 0).
SELECT * FROM information_schema.function_cache;
+--------------------+--------------+------+
| ID | FUNCTION | SIZE |
+--------------------+--------------+------+
| xx.xx.xx.xx:3000 | mysql.my_mul | 0 |
| yy.yy.yy.yy:3100 | mysql.my_mul | 0 |
+--------------------+--------------+------+
-- Call the UDF. This triggers the function body to load on one node.
SELECT my_mul(2, 2);
+--------------+
| my_mul(2, 2) |
+--------------+
| 124 |
+--------------+
-- The body is now loaded on the node that executed the call (SIZE = 79).
SELECT * FROM information_schema.function_cache;
+--------------------+--------------+------+
| ID | FUNCTION | SIZE |
+--------------------+--------------+------+
| xx.xx.xx.xx:3000 | mysql.my_mul | 0 |
| yy.yy.yy.yy:3100 | mysql.my_mul | 79 |
+--------------------+--------------+------+
SELECT * FROM information_schema.function_cache_capacity;
+--------------------+-----------+-------------+
| ID | USED_SIZE | TOTAL_SIZE |
+--------------------+-----------+-------------+
| xx.xx.xx.xx:3000 | 0 | 15139759718 |
| yy.yy.yy.yy:3100 | 79 | 15139759718 |
+--------------------+-----------+-------------+
-- Reload the UDF to reset the cache on all nodes.
RELOAD FUNCTIONS;
-- All nodes show SIZE = 0 again.
SELECT * FROM information_schema.function_cache;
+--------------------+--------------+------+
| ID | FUNCTION | SIZE |
+--------------------+--------------+------+
| xx.xx.xx.xx:3000 | mysql.my_mul | 0 |
| yy.yy.yy.yy:3100 | mysql.my_mul | 0 |
+--------------------+--------------+------+リソース管理
メモリ制限
UDF 実行中、メモリは主にカーソルによって使用されます。メモリ制限を設定するには、次のパラメーターを使用します。
| パラメーター | 説明 |
|---|---|
PL_CURSOR_MEMORY_LIMIT | 単一カーソルの最大メモリ。超過した場合、データはディスクにスピルします。少なくとも 128 KB (131072) に設定します。 |
PL_MEMORY_LIMIT | UDF の最大メモリ。PL_CURSOR_MEMORY_LIMIT 以上である必要があります。 |
UDF を呼び出すクエリ全体のメモリも制限されます。
呼び出し深度制限
MAX_PL_DEPTH パラメーターを使用して UDF 呼び出し深度を制限します。深い呼び出しスタックはデバッグが困難であり、かなりのリソースを消費します。