すべてのプロダクト
Search
ドキュメントセンター

AnalyticDB:UDFs

最終更新日:Dec 16, 2025

AnalyticDB for MySQL では、REMOTE_CALL() 関数を使用して、Function Compute で作成したカスタム関数を呼び出すことができます。これにより、AnalyticDB for MySQL でユーザー定義関数 (UDF) を使用できます。

前提条件

  • ご利用のクラスターのカーネルバージョンが 3.2.1.0 以降であること。

  • クラスターと Function Compute サービスが同じリージョンにあること。詳細については、Function Compute の有効化をご参照ください。

  • ユーザー定義関数が作成されていること

    説明

    関数呼び出し時の Function Compute の起動時間を短縮するために、ユーザー定義関数を作成する際は、[ランタイム環境] で Python、Go、または Node.js を選択することを推奨します。

仕組み

AnalyticDB for MySQL のリモート UDF 機能は、Function Compute をリモート関数サーバーとして使用します。AnalyticDB for MySQL の REMOTE_CALL() 関数を使用して、Function Compute で事前定義された UDF を呼び出すことができます。以下のフローチャートにそのプロセスを示します。

image
  1. クライアントが SQL 文を AnalyticDB for MySQL に送信します。

  2. REMOTE_CALL() 関数が呼び出されると、AnalyticDB for MySQL はデータを JSON フォーマットで Function Compute に送信します。

  3. Function Compute はユーザー定義関数を使用してデータを処理します。

  4. Function Compute は結果を JSON フォーマットで AnalyticDB for MySQL に返します。

  5. AnalyticDB for MySQL は最終結果をクライアントに返します。

注意事項

リモート UDF 機能は、スカラー UDF のみをサポートします。

構文

remote_call('returnType', 'func_name', ['{external_config}'|NULL], X1, X2, ..., Xn)

パラメーター

パラメーター

説明

returnType

戻り値のデータ型。BOOLEAN、DOUBLE、VARCHAR、INTEGER、TINYINT、BIGINT、TIME、DATE、TIMESTAMP、DATETIME のデータ型のみがサポートされます。

func_name

Function Compute で作成したユーザー定義関数の名前。

  • Function Compute のバージョンが 3.0 の場合は、ユーザー定義関数の名前のみを指定します。

  • Function Compute のバージョンが 2.0 の場合は、サービス名と関数名をドル記号 ($) で連結して指定します。フォーマット: serviceName$functionName

説明

Function Compute コンソールにログインして、Function Compute のバージョンを確認します。

external_config|null

関数呼び出しの拡張パラメーター。拡張パラメーターを使用しない場合は、null を指定します。拡張パラメーターは JSON フォーマットである必要があります。複数のパラメーターはカンマ (,) で区切ります。

クエリで拡張パラメーターを設定するか、SET ADB_CONFIG コマンドを使用してグローバルパラメーターを設定できます。パラメーターがクエリレベルとグローバルレベルの両方で設定されている場合、クエリレベルのパラメーターが優先されます。拡張パラメーターの詳細については、external_config でサポートされる拡張パラメーターをご参照ください。

X1.......Xn

入力パラメーター。BOOLEAN、DOUBLE、VARCHAR、INTEGER、TINYINT、BIGINT、TIME、DATE、TIMESTAMP、DATETIME のデータ型のみがサポートされます。

external_config でサポートされる拡張パラメーターは次のとおりです。

グローバルパラメーター

クエリレベルのパラメーター

必須

説明

XIHE_REMOTE_CALL_SERVER_ENDPOINT

endpoint

はい

Function Compute の内部サービスエンドポイント。詳細については、サービスエンドポイントをご参照ください。

XIHE_REMOTE_CALL_SERVER_AK

-

特定の条件下で必須

Function Compute に対するサービス管理権限を持つ Alibaba Cloud アカウントまたは Resource Access Management (RAM) ユーザーの AccessKey ID。

  • ご利用の AnalyticDB for MySQL クラスターが Data Warehouse Edition クラスターの場合、AccessKey ID を設定する必要があります。

  • ご利用の AnalyticDB for MySQL クラスターが Enterprise Edition、Basic Edition、および Data Lakehouse Edition クラスターの場合:

    • 同一アカウント内の Function Compute サービスにアクセスする場合、セキュリティトークンサービス (STS) が自動的に認証に使用されます。 AccessKey ID を設定する必要はありません。

    • Function Compute サービスへのクロスアカウントアクセスを実行する場合、AccessKey ID を設定する必要があります。

AccessKey ID の取得方法の詳細については、アカウントと権限をご参照ください。

重要

XIHE_REMOTE_CALL_SERVER_AK パラメーターは、グローバルパラメーターとしてのみ設定できます。

XIHE_REMOTE_CALL_SERVER_SK

-

特定の条件下で必須

Function Compute に対するサービス管理権限を持つ Alibaba Cloud アカウントまたは RAM ユーザーの AccessKey Secret。

  • ご利用の AnalyticDB for MySQL クラスターが Data Warehouse Edition クラスターの場合、AccessKey Secret を設定する必要があります。

  • ご利用の AnalyticDB for MySQL クラスターが Enterprise Edition、Basic Edition、および Data Lakehouse Edition クラスターの場合:

    • 同一アカウント内の Function Compute サービスにアクセスする場合、STS が自動的に認証に使用されます。 AccessKey Secret を設定する必要はありません。

    • Function Compute サービスへのクロスアカウントアクセスを実行する場合、AccessKey Secret を設定する必要があります。

AccessKey Secret の取得方法の詳細については、アカウントと権限をご参照ください。

重要

XIHE_REMOTE_CALL_SERVER_SK パラメーターは、グローバルパラメーターとしてのみ設定できます。

XIHE_REMOTE_CALL_COMPRESS_ENABLED

compressed

いいえ

AnalyticDB for MySQL がデータを Function Compute に送信する前に、データを GZIP フォーマットに圧縮するかどうかを指定します。有効値:

  • true (デフォルト): データを圧縮します。

  • false: いいえ。

XIHE_REMOTE_CALL_MAX_BATCH_SIZE

max_batch_size

いいえ

REMOTE_CALL() 関数が呼び出された後、各バッチで Function Compute に送信できるデータ行の最大数。デフォルトでは、制限はありません。データ行の数を少なくすると、Function Compute の CPU とメモリの負荷が軽減されますが、クエリの実行時間は長くなります。

Function Compute でのユーザー定義関数の例

REMOTE_CALL() 関数が呼び出されると、AnalyticDB for MySQL はデータを JSON フォーマットで Function Compute に送信します。データが処理された後、Function Compute は結果を JSON フォーマットで返します。Function Compute でユーザー定義関数を作成する際は、指定されたデータ送信および返却フォーマットに準拠する必要があります。

データ送受信フォーマット

データ送信フォーマット

{
  "rowCount": 3, 
  "compressed":true, 
  "data": 
  [
      [1, "a", "2023-08-22 11:30:00"],
      [2, "b", "2023-08-22 12:30:00"],
      [3, "c", null]
  ]
}

JSON データ構造:

  • rowCount: データ行の数。

  • compressed: 送信データが圧縮されているかどうかを指定します。有効値: true および false

  • data: 送信データ。このパラメーターは複数の JSON 配列で構成されます。各 JSON 配列は 1 行のデータを表します。

データ返却フォーマット

{
  "success": true,   
  "message": "",  
  "result" : [  ] 
}

JSON データ構造:

  • success: リクエストが成功したかどうかを示します。有効値: true および false

  • message: 詳細情報。リクエストが成功した場合、このパラメーターは空です。リクエストが失敗した場合、このパラメーターにはエラーメッセージが含まれます。

  • result: Function Compute で計算された結果。

この例では、Function Compute で作成されたユーザー定義関数は ConcactNumberWithCompress という名前です。以下にサンプルコードを示します。

public class App
        implements StreamRequestHandler, FunctionInitializer
{
    public static final Logger log = Logger.getLogger(App.class.getName());

    public void initialize(Context context)
            throws IOException
    {
        // TODO
    }

    @Override
    public void handleRequest(
            InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException
    {
        InputStream notCompressedInputStream1;
        notCompressedInputStream1 = tryUnCompress(inputStream);

        JSONObject response = new JSONObject();
        try {
            JSONObject requestJson = JSONObject.parseObject(IOUtils.toString(notCompressedInputStream1));
            if (requestJson.containsKey("data")) {
                JSONArray result = new JSONArray();
                JSONArray data = requestJson.getJSONArray("data");
                for (int i = 0; i < data.size(); i++) {
                    JSONArray row = data.getJSONJSONArray(i);
                    // ここに Function Compute のビジネスロジックを実装します。
                    // この関数には a と b の 2 つの入力パラメーターがあると仮定します。AnalyticDB for MySQL から送信される各データ行には 2 つの数値が含まれます。最初の数値が a で、2 番目の数値が b です。
                    if (row.size() == 2) {
                        result.add(testFunc(row.getInteger(0), row.getInteger(1)));
                    }
                    else {
                        throw new RuntimeException("row size is not 2");
                    }
                    // Function Compute のビジネスロジックはここで終了します。
                }

                response.put("result", result);
                response.put("success", true);
                response.put("message", "");
            }
            else {
                response.put("success", false);
                response.put("message", "no data inside");
            }
        }
        catch (Exception e) {
            log.info("error happened" + e.getMessage());
            response.put("success", false);
            response.put("message", e.getMessage());
        }

        outputStream.write(tryCompress(response.toJSONString().getBytes()));
    }

    private String testFunc(int a, int b)
    {
        // テスト関数は、入力パラメーター a と b、および数値 1 をアンパサンド (&) を使用して連結します。
        return String.valueOf(a) + '&' + b + '&' + 1;
    }

    public static byte[] tryCompress(byte[] bytes)
    {
        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
        try {
            GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteOutputStream);
            gzipOutputStream.write(bytes);
            gzipOutputStream.close();
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }

        return byteOutputStream.toByteArray();
    }

    public static InputStream tryUnCompress(InputStream inputStream)
            throws IOException
    {
        GZIPInputStream gzipInputStream;
        gzipInputStream = new GZIPInputStream(inputStream);
        return gzipInputStream;
    }
}

REMOTE_CALL 関数を AnalyticDB for MySQL で呼び出す例

  • グローバルパラメーターが設定されていない場合、ConcactNumberWithCompress ユーザー定義関数を呼び出して、12 をアンパサンド (&) で連結します:

    SELECT remote_call('varchar','ConcactNumberWithCompress','{endpoint:"1234567890000****.cn-zhangjiakou-internal.fc.aliyuncs.com"}',1,2);

    次の結果が返されます:

    1&2&1
  • グローバルパラメーターが設定されていない場合、ConcactNumberWithCompress ユーザー定義関数を呼び出して、34 をアンパサンド (&) で連結します:

    SELECT remote_call('varchar','ConcactNumberWithCompress','{endpoint:"1234567890000****.cn-zhangjiakou-internal.fc.aliyuncs.com",compressed:false,max_batch_size:5000000}',3,4);

    次の結果が返されます:

    3&4&1
  • グローバルパラメーターが設定されている場合、ConcactNumberWithCompress ユーザー定義関数を呼び出して、56 をアンパサンド (&) で連結します:

    SELECT remote_call('varchar','ConcactNumberWithCompress',null,5,6);

    以下の結果が返されます:

    5&6&1

よくある質問

REMOTE_CALL 関数を呼び出すと、なぜ java.util.zip.ZipException: Not in GZIP format エラーが発生するのですか?

  • AnalyticDB for MySQL はデータを GZIP フォーマットに圧縮して Function Compute に送信しますが、Function Compute で作成されたユーザー定義関数に展開コードが含まれていないため、Function Compute はデータを解析できません。

  • AnalyticDB for MySQL は非圧縮データを Function Compute に送信します。処理後、Function Compute は結果を GZIP フォーマットを使用して圧縮し、AnalyticDB for MySQL に返します。その結果、AnalyticDB for MySQL はデータを解析できません。

REMOTE_CALL 関数を呼び出すと、なぜ parse remote_call config error エラーが発生するのですか?

REMOTE_CALL 関数の external_config パラメーターの構文が正しくありません。SQL 文を確認して修正し、再度実行してください。