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 を呼び出すことができます。以下のフローチャートにそのプロセスを示します。
クライアントが SQL 文を AnalyticDB for MySQL に送信します。
REMOTE_CALL() 関数が呼び出されると、AnalyticDB for MySQL はデータを JSON フォーマットで Function Compute に送信します。
Function Compute はユーザー定義関数を使用してデータを処理します。
Function Compute は結果を JSON フォーマットで AnalyticDB for MySQL に返します。
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 コンソールにログインして、Function Compute のバージョンを確認します。 |
external_config|null | 関数呼び出しの拡張パラメーター。拡張パラメーターを使用しない場合は、null を指定します。拡張パラメーターは JSON フォーマットである必要があります。複数のパラメーターはカンマ (,) で区切ります。 クエリで拡張パラメーターを設定するか、 |
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。
AccessKey ID の取得方法の詳細については、アカウントと権限をご参照ください。 重要 XIHE_REMOTE_CALL_SERVER_AK パラメーターは、グローバルパラメーターとしてのみ設定できます。 |
XIHE_REMOTE_CALL_SERVER_SK | - | 特定の条件下で必須 | Function Compute に対するサービス管理権限を持つ Alibaba Cloud アカウントまたは RAM ユーザーの AccessKey Secret。
AccessKey Secret の取得方法の詳細については、アカウントと権限をご参照ください。 重要 XIHE_REMOTE_CALL_SERVER_SK パラメーターは、グローバルパラメーターとしてのみ設定できます。 |
XIHE_REMOTE_CALL_COMPRESS_ENABLED | compressed | いいえ | AnalyticDB for MySQL がデータを Function Compute に送信する前に、データを GZIP フォーマットに圧縮するかどうかを指定します。有効値:
|
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 でユーザー定義関数を作成する際は、指定されたデータ送信および返却フォーマットに準拠する必要があります。
この例では、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 ユーザー定義関数を呼び出して、
1と2をアンパサンド (&) で連結します:SELECT remote_call('varchar','ConcactNumberWithCompress','{endpoint:"1234567890000****.cn-zhangjiakou-internal.fc.aliyuncs.com"}',1,2);次の結果が返されます:
1&2&1グローバルパラメーターが設定されていない場合、ConcactNumberWithCompress ユーザー定義関数を呼び出して、
3と4をアンパサンド (&) で連結します: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 ユーザー定義関数を呼び出して、
5と6をアンパサンド (&) で連結します: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 文を確認して修正し、再度実行してください。