Todos os produtos
Search
Central de documentação

AnalyticDB:UDFs

Última atualização: Jun 27, 2026

O AnalyticDB for MySQL oferece suporte à função REMOTE_CALL(), que permite invocar funções definidas pelo usuário (UDFs) personalizadas hospedadas no Function Compute diretamente via SQL. Apenas UDFs escalares são suportadas.

Pré-requisitos

Antes de começar, verifique se você possui:

  • Um cluster do AnalyticDB for MySQL executando a versão do kernel 3.2.1.0 ou posterior

  • O cluster e seu serviço do Function Compute na mesma região

  • Uma UDF criada no Function Compute

Para obter tempos de inicialização a frio mais rápidos, selecione Python , Go ou Node.js como o Runtime Environment ao criar a UDF.

Como funciona

O Function Compute atua como o servidor de funções remotas. Quando a função REMOTE_CALL() é invocada em uma instrução SQL, o AnalyticDB for MySQL envia dados ao Function Compute no formato JSON e retorna o resultado ao cliente.

image

  1. Um cliente envia uma instrução SQL ao AnalyticDB for MySQL.

  2. Após a chamada da função REMOTE_CALL(), o AnalyticDB for MySQL transmite os dados ao Function Compute no formato JSON.

  3. O Function Compute processa os dados utilizando sua UDF.

  4. O Function Compute devolve o resultado ao AnalyticDB for MySQL no formato JSON.

  5. O AnalyticDB for MySQL entrega o resultado final ao cliente.

Sintaxe

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

Parâmetros

Parâmetro

Descrição

returnType

Tipo de dados do valor de retorno. Valores válidos: BOOLEAN, DOUBLE, VARCHAR, INTEGER, TINYINT, BIGINT, TIME, DATE, TIMESTAMP, DATETIME.

func_name

Nome da UDF no Function Compute. Para o Function Compute 3.0, especifique apenas o nome da função. Para o Function Compute 2.0, utilize o formato serviceName$functionName. Acesse o console do Function Compute para verificar a versão.

external_config

NULL

Configuração estendida no formato JSON. Especifique NULL caso não seja necessário. As definições no nível da consulta substituem as configurações globais definidas com SET ADB_CONFIG. Para mais detalhes, consulte Parâmetros estendidos para external_config.

X1...Xn

Parâmetros de entrada. Valores válidos: BOOLEAN, DOUBLE, VARCHAR, INTEGER, TINYINT, BIGINT, TIME, DATE, TIMESTAMP, DATETIME.

Parâmetros estendidos para external_config

Defina os parâmetros de external_config no nível da consulta ou configure-os globalmente usando SET ADB_CONFIG. As configurações no nível da consulta têm precedência sobre as configurações globais.

Parâmetro global

Parâmetro no nível da consulta

Obrigatório

Descrição

XIHE_REMOTE_CALL_SERVER_ENDPOINT

endpoint

Sim

Endpoint de serviço interno do Function Compute. Para mais detalhes, consulte Endpoints de serviço.

XIHE_REMOTE_CALL_SERVER_AK

Condicional

AccessKey ID da conta Alibaba Cloud ou do usuário do Resource Access Management (RAM) com permissões no Function Compute. Obrigatório para clusters da Data Warehouse Edition. Nos clusters das edições Enterprise, Basic e Data Lakehouse, o Security Token Service (STS) gerencia a autenticação automaticamente para acesso na mesma conta; o acesso entre contas exige o AccessKey ID. Pode ser definido apenas como parâmetro global. Para mais detalhes, consulte Contas e permissões.

XIHE_REMOTE_CALL_SERVER_SK

Condicional

AccessKey secret da conta Alibaba Cloud ou do usuário RAM. Segue as mesmas condições de XIHE_REMOTE_CALL_SERVER_AK. Pode ser definido apenas como parâmetro global.

XIHE_REMOTE_CALL_COMPRESS_ENABLED

compressed

Não

Determina se o payload de dados deve ser compactado no formato GZIP antes do envio ao Function Compute. Padrão: true.

XIHE_REMOTE_CALL_MAX_BATCH_SIZE

max_batch_size

Não

Número máximo de linhas enviadas ao Function Compute por lote. Padrão: sem limite. Um tamanho de lote menor reduz a pressão sobre CPU e memória no Function Compute, mas aumenta o tempo de consulta.

Importante

Os parâmetros XIHE_REMOTE_CALL_SERVER_AK e XIHE_REMOTE_CALL_SERVER_SK só podem ser configurados como parâmetros globais por meio de SET ADB_CONFIG.

Escreva um handler do Function Compute

Sua UDF deve aceitar entradas e retornar resultados no formato JSON utilizado pela função REMOTE_CALL().

Formatos de envio e retorno de dados

Formato de entrada

O AnalyticDB for MySQL envia dados ao Function Compute na seguinte estrutura JSON:

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

Campo

Descrição

rowCount

Quantidade de linhas no lote.

compressed

Indica se os dados transmitidos estão compactados. Valores válidos: true e false.

data

Dados transmitidos. Este campo consiste em múltiplos arrays JSON, onde cada array representa uma linha de dados.

Formato de saída

O Function Compute deve retornar os resultados na seguinte estrutura JSON:

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

Campo

Descrição

success

Indica se a requisição foi bem-sucedida. Valores válidos: true e false.

message

Vazio em caso de sucesso. Contém a mensagem de erro em caso de falha.

result

Resultado computado no Function Compute.

Exemplo: handler Java

O exemplo a seguir implementa ConcactNumberWithCompress, que recebe dois inteiros a e b e retorna a string "a&b&1".

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
    {
        // Step 1: Decompress the input.
        // REMOTE_CALL() compresses data with GZIP by default (compressed=true).
        // If you set compressed=false in external_config, skip this step.
        InputStream decompressedInput = tryUnCompress(inputStream);

        JSONObject response = new JSONObject();
        try {
            // Step 2: Parse the JSON body sent by AnalyticDB for MySQL.
            // The body has the structure: {"rowCount": N, "compressed": true/false, "data": [[...], ...]}
            JSONObject requestJson = JSONObject.parseObject(IOUtils.toString(decompressedInput));
            if (requestJson.containsKey("data")) {
                JSONArray result = new JSONArray();
                // Step 3: Iterate over the rows in the "data" array.
                // Each row is a JSON array whose columns match the X1...Xn parameter order in REMOTE_CALL().
                // This function expects two integers: X1 (index 0) and X2 (index 1).
                JSONArray data = requestJson.getJSONArray("data");
                for (int i = 0; i < data.size(); i++) {
                    JSONArray row = data.getJSONArray(i);
                    if (row.size() == 2) {
                        result.add(testFunc(row.getInteger(0), row.getInteger(1)));
                    } else {
                        throw new RuntimeException("row size is not 2");
                    }
                }
                // Step 4: Build the response.
                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());
        }

        // Step 5: Compress the response.
        // REMOTE_CALL() expects a GZIP-compressed response when compressed=true (the default).
        // If you set compressed=false in external_config, remove this compression step.
        outputStream.write(tryCompress(response.toJSONString().getBytes()));
    }

    private String testFunc(int a, int b) {
        // Concatenate a, b, and 1 with ampersands.
        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 {
        return new GZIPInputStream(inputStream);
    }
}

Exemplos

Chamada com configuração no nível da consulta

Passe o endpoint do Function Compute diretamente no parâmetro external_config:

-- Concatenate 1 and 2 with an ampersand
SELECT remote_call(
  'varchar',
  'ConcactNumberWithCompress',
  '{endpoint:"1234567890000****.cn-zhangjiakou-internal.fc.aliyuncs.com"}',
  1, 2
);
-- Result: 1&2&1

Desative a compactação GZIP e defina um limite de tamanho de lote:

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

Chamada com configuração global

Configure os parâmetros globais uma única vez usando SET ADB_CONFIG e, em seguida, omita external_config nas chamadas subsequentes:

SELECT remote_call('varchar', 'ConcactNumberWithCompress', null, 5, 6);
-- Result: 5&6&1

Solução de problemas

java.util.zip.ZipException: Not in GZIP format

Este erro geralmente ocorre por dois motivos:

  • Incompatibilidade de descompactação na entrada: O AnalyticDB for MySQL compacta os dados no formato GZIP e os envia ao Function Compute, mas a função definida pelo usuário criada no Function Compute não contém código de descompactação. Consequentemente, o Function Compute não consegue analisar os dados.

  • Incompatibilidade de compactação na saída: O AnalyticDB for MySQL envia dados não compactados ao Function Compute. Após o processamento, o Function Compute compacta o resultado usando o formato GZIP e o retorna ao AnalyticDB for MySQL. Como resultado, o AnalyticDB for MySQL não consegue analisar os dados.

parse remote_call config error

O JSON de external_config está malformado. Verifique a sintaxe do valor de external_config em sua instrução SQL, corrija-o e execute a consulta novamente.