Consulta con funciones definidas por el usuario - Amazon Athena

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Consulta con funciones definidas por el usuario

Las funciones definidas por el usuario (UDF) en Amazon Athena le permiten crear funciones personalizadas para procesar registros o grupos de registros. Una UDF acepta parámetros, realiza el trabajo y, a continuación, devuelve un resultado.

Para utilizar una UDF en Athena, escriba una cláusula USING EXTERNAL FUNCTION antes de una instrucción SELECT en una consulta SQL. La instrucción SELECT hace referencia a la UDF y define las variables que se pasan a la UDF cuando se ejecuta la consulta. La consulta SQL invoca una función Lambda mediante el tiempo de ejecución de Java cuando llama a la UDF. Las UDF se definen dentro de la función Lambda como métodos en un paquete de implementación de Java. Se pueden definir varias UDF en el mismo paquete de implementación de Java para una función Lambda. También se especifica el nombre de la función Lambda en la cláusula USING EXTERNAL FUNCTION.

Tiene dos opciones para implementar una función Lambda para UDF de Athena. Puede implementar la función directamente mediante Lambda, o puede usar AWS Serverless Application Repository. Para buscar funciones Lambda existentes para UDF, puede buscar en el repositorio público AWS Serverless Application Repository o su repositorio privado y, a continuación, realizar la implementación en Lambda. También puede crear o modificar el código fuente Java, empaquetarlo en un archivo JAR e implementarlo mediante Lambda o AWS Serverless Application Repository. Para ver un ejemplo de código fuente Java y paquetes para empezar, consulte Creación e implementación de una UDF mediante Lambda. Para obtener más información acerca de Lambda, consulte la Guía para desarrolladores de AWS Lambda. Para obtener más información sobre AWS Serverless Application Repository, consulte la AWS Serverless Application RepositoryGuía para desarrolladores de .

Para ver un ejemplo que utiliza UDF con Athena para traducir y analizar texto, consulte el artículo del blog de Machine Learning AWS Traducir y analizar texto mediante funciones SQL con Amazon Athena, Amazon Translate y Amazon Comprehend, o vea el video.

Para ver un ejemplo del uso de UDF a fin de ampliar las consultas geoespaciales en Amazon Athena, consulte Extend geospatial queries in Amazon Athena with UDFs and AWS Lambda en el blog sobre macrodatos de AWS.

Condiciones y limitaciones

  • Funciones de Athena integradas: las funciones integradas en Athena se han diseñado para tener un alto rendimiento. Se recomienda utilizar funciones prediseñadas sobre UDF cuando sea posible. Para obtener más información sobre funciones prediseñadas, consulte Funciones en Amazon Athena.

  • Únicamente UDF escalares: Athena solo admite UDF escalares, que procesan una fila a la vez y devuelven un único valor de columna. Athena pasa un lote de filas, potencialmente en paralelo, a la UDF cada vez que invoca Lambda. Al diseñar UDF y consultas, tenga en cuenta el impacto potencial en el tráfico de red de este procesamiento.

  • Funciones del controlador de la FDU utilizan un formato abreviado: utilice el formato abreviado (no formato completo), para las funciones de la FDU (por ejemplo, package.Class en lugar de package.Class::method).

  • Los métodos de la FDU deben ir en minúscula: los métodos de la FDU deben estar en minúsculas; no se permite la combinación entre mayúsculas y minúsculas.

  • Los métodos de UDF requieren parámetros: los métodos de UDF deben tener al menos un parámetro de entrada. Si se intenta invocar una UDF definida sin parámetros de entrada, se produce una excepción en el tiempo de ejecución. Las UDF se han diseñado para desarrollar funciones con registros de datos, pero una UDF sin argumentos no acepta datos, por lo que se produce una excepción.

  • Soporte de tiempo de ejecución en Java: actualmente, las UDF de Athena admiten los tiempos de ejecución de Java 8 y Java 11 para Lambda. Para obtener más información, consulte Creación de funciones Lambda con Java en la Guía para desarrolladores de AWS Lambda.

  • Permisos de IAM: para ejecutar y crear instrucciones de consulta UDF en Athena, la entidad principal de IAM que ejecuta la consulta debe tener permiso para realizar acciones además de las funciones de Athena. Para obtener más información, consulte Ejemplos de políticas de permisos de IAM para permitir funciones definidas por el usuario (UDF) de Amazon Athena.

  • Cuotas de Lambda: las cuotas de Lambda se aplican a las UDF. Para obtener más información, consulte Cuotas de Lambda en la Guía para desarrolladores de AWS Lambda.

  • Filtrado a nivel de fila: el filtrado a nivel de fila de Lake Formation no es compatible con las UDF.

  • Vistas: no se pueden utilizar vistas con UDF.

  • Problemas conocidos: para obtener la lista más actualizada de problemas conocidos, consulte Limitations and issues (Limitaciones y problemas) en la sección awslabs/aws-athena-query-federation de GitHub.

Videos

Mire los siguientes videos para obtener más información acerca del uso de las UDF en Athena.

Video: presentación de las funciones definidas por el usuario (UDF) en Amazon Athena

En el siguiente video, se muestra cómo utilizar UDF en Amazon Athena para redactar información confidencial.

nota

La sintaxis de este video es una versión preliminar, pero los conceptos son los mismos. Utilice Athena sin el grupo de trabajo AmazonAthenaPreviewFunctionality.

Video
: Traducir, analizar y redactar campos de texto mediante consultas SQL en Amazon Athena

En el siguiente video, se muestra cómo utilizar UDF en Amazon Athena junto con otros Servicios de AWS para traducir y analizar texto.

nota

La sintaxis de este video es una versión preliminar, pero los conceptos son los mismos. Para obtener la sintaxis correcta, consulte la publicación del blog relacionada Traducir, redactar y analizar texto mediante funciones SQL con Amazon Athena, Amazon Translate y Amazon Comprehend en el blog de Machine Learning de AWS.

Sintaxis de la consulta de UDF

La cláusula USING EXTERNAL FUNCTION especifica una UDF o varias UDF a las que se puede hacer referencia mediante una instrucción SELECT posterior en la consulta. Necesita el nombre del método para la UDF y el nombre de la función Lambda que aloja la UDF. En lugar del nombre de la función de Lambda, puede utilizar el ARN de Lambda. En escenarios de varias cuentas, se requiere el ARN de Lambda.

Sinopsis

USING EXTERNAL FUNCTION UDF_name(variable1 data_type[, variable2 data_type][,...]) RETURNS data_type LAMBDA 'lambda_function_name_or_ARN' [, EXTERNAL FUNCTION UDF_name2(variable1 data_type[, variable2 data_type][,...]) RETURNS data_type LAMBDA 'lambda_function_name_or_ARN'[,...]] SELECT [...] UDF_name(expression) [, UDF_name2(expression)] [...]

Parámetros

USING EXTERNAL FUNCTION UDF_name(variable1 data_type[, variable2 data_type][,...])

UDF_name especifica el nombre de la UDF, que debe corresponderse con un método Java dentro de la función Lambda de referencia. Cada variable data_type especifica una variable con nombre con su tipo de datos correspondiente, que la UDF acepta como entrada. El data_type debe ser uno de los tipos de datos de Athena admitidos que aparecen en la tabla siguiente y asignarse al tipo de datos Java correspondiente.

Tipo de datos de Athena Tipo de datos Java

TIMESTAMP

java.time.LocalDateTime (UTC)

DATE

java.time.LocalDate (UTC)

TINYINT

java.lang.Byte

SMALLINT

java.lang.Short

REAL

java.lang.Float

DOUBLE

java.lang.Double

DECIMAL (consulte la nota RETURNS)

java.math.BigDecimal

BIGINT

java.lang.Long

INTEGER

java.lang.Int

VARCHAR

java.lang.String

VARBINARY

byte[]

BOOLEANO

java.lang.Boolean

ARRAY

java.util.List

ROW

java.util.Map<String, Object>

RETURNS data_type

data_type especifica el tipo de datos SQL que la UDF devuelve a la consulta como salida. Los tipos de datos de Athena enumerados en la tabla anterior son compatibles. Para el tipo de datos DECIMAL, utilice la sintaxis RETURNS DECIMAL(precision, scale) donde precision y scale son enteros.

LAMBDA 'lambda_function'

lambda_function especifica el nombre de la función Lambda que se va a invocar cuando se ejecuta la UDF.

SELECT [...] UDF_name(expression) [...]

La consulta SELECT que pasa valores a la UDF y devuelve un resultado. UDF_name especifica la UDF que se va a utilizar, seguida de una expression (expresión) que se evalúa para pasar valores. Los valores que se pasan y se devuelven deben coincidir con los tipos de datos correspondientes especificados para la UDF en la cláusula USING EXTERNAL FUNCTION.

Ejemplos

Para ver ejemplos de consultas basadas en el código AthenaUDFHandler.java en GitHub, consulte la página Conector UDF de Amazon Athena.

Creación e implementación de una UDF mediante Lambda

Para crear una UDF personalizada, cree una nueva clase Java mediante la extensión de la clase UserDefinedFunctionHandler. El código fuente de UserDefinedFunctionHandler.java en el SDK está disponible en GitHub en el repositorio awslabs/aws-athena-query-federation/athena-federation-sdk, junto con implementaciones de UDF de ejemplo que puede examinar y modificar para crear una UDF personalizada.

Los pasos de esta sección muestran cómo escribir y crear un archivo Jar de UDF personalizado mediante Apache Maven desde la línea de comandos y una implementación.

Clonación del SDK y preparación del entorno de desarrollo

Antes de comenzar, asegúrese de que git esté instalado en su sistema mediante sudo yum install git -y.

Para instalar el SDK de federación de consultas de AWS
  • Escriba lo siguiente en la línea de comandos para clonar el repositorio de SDK. Este repositorio incluye el SDK, ejemplos y un conjunto de conectores de origen de datos. Para obtener más información sobre los conectores de origen de datos, consulte Uso de consulta federada de Amazon Athena.

    git clone https://github.com/awslabs/aws-athena-query-federation.git
Para instalar los requisitos previos para este procedimiento, tenga en cuenta lo siguiente:

Si está trabajando en un equipo de desarrollo que ya tiene instalado Apache Maven, la AWS CLI y la herramienta de compilación de AWS Serverless Application Model, puede omitir este paso.

  1. Desde la raíz del directorio aws-athena-query-federation que creó cuando realizó la clonación, ejecute el script prepare_dev_env.sh que prepara el entorno de desarrollo.

  2. Actualice el shell para generar nuevas variables creadas por el proceso de instalación o reinicie la sesión de terminal.

    source ~/.profile
    importante

    Si omite este paso, obtendrá errores más adelante acerca de que la herramienta de compilación de la AWS CLI o el AWS SAM no puede publicar su función Lambda.

Creación del proyecto de Maven

Ejecute el siguiente comando para crear el proyecto de Maven. Reemplace groupId por el ID único de su organización y sustituya my-athena-udf por el nombre de su aplicación. Para obtener más información, consulte ¿Cómo realizo mi primer proyecto de Maven? en la documentación de Apache Maven.

mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DgroupId=groupId \ -DartifactId=my-athena-udfs

Adición de dependencias y complementos al proyecto de Maven

Agregue las siguientes configuraciones al archivo pom.xml del proyecto de Maven. Para ver un ejemplo, consulte el archivo pom.xml en GitHub.

<properties> <aws-athena-federation-sdk.version>2021.6.1</aws-athena-federation-sdk.version> </properties> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-athena-federation-sdk</artifactId> <version>${aws-athena-federation-sdk.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.1</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build>

Escritura de código Java para las UDF

Extienda UserDefinedFunctionHandler.java para crear una nueva clase. Escriba sus UDF dentro de la clase.

En el siguiente ejemplo, se crean dos métodos Java para UDF compress() y decompress(), dentro de la clase MyUserDefinedFunctions.

*package *com.mycompany.athena.udfs; public class MyUserDefinedFunctions extends UserDefinedFunctionHandler { private static final String SOURCE_TYPE = "MyCompany"; public MyUserDefinedFunctions() { super(SOURCE_TYPE); } /** * Compresses a valid UTF-8 String using the zlib compression library. * Encodes bytes with Base64 encoding scheme. * * @param input the String to be compressed * @return the compressed String */ public String compress(String input) { byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8); // create compressor Deflater compressor = new Deflater(); compressor.setInput(inputBytes); compressor.finish(); // compress bytes to output stream byte[] buffer = new byte[4096]; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length); while (!compressor.finished()) { int bytes = compressor.deflate(buffer); byteArrayOutputStream.write(buffer, 0, bytes); } try { byteArrayOutputStream.close(); } catch (IOException e) { throw new RuntimeException("Failed to close ByteArrayOutputStream", e); } // return encoded string byte[] compressedBytes = byteArrayOutputStream.toByteArray(); return Base64.getEncoder().encodeToString(compressedBytes); } /** * Decompresses a valid String that has been compressed using the zlib compression library. * Decodes bytes with Base64 decoding scheme. * * @param input the String to be decompressed * @return the decompressed String */ public String decompress(String input) { byte[] inputBytes = Base64.getDecoder().decode((input)); // create decompressor Inflater decompressor = new Inflater(); decompressor.setInput(inputBytes, 0, inputBytes.length); // decompress bytes to output stream byte[] buffer = new byte[4096]; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length); try { while (!decompressor.finished()) { int bytes = decompressor.inflate(buffer); if (bytes == 0 && decompressor.needsInput()) { throw new DataFormatException("Input is truncated"); } byteArrayOutputStream.write(buffer, 0, bytes); } } catch (DataFormatException e) { throw new RuntimeException("Failed to decompress string", e); } try { byteArrayOutputStream.close(); } catch (IOException e) { throw new RuntimeException("Failed to close ByteArrayOutputStream", e); } // return decoded string byte[] decompressedBytes = byteArrayOutputStream.toByteArray(); return new String(decompressedBytes, StandardCharsets.UTF_8); } }

Creación del archivo JAR

Ejecute mvn clean install para crear su proyecto. Después de que se compile correctamente, se crea un archivo JAR en la carpeta target de su proyecto denominada artifactId-version.jar, donde artifactId es el nombre que proporcionó en el proyecto de Maven, por ejemplo, my-athena-udfs.

Implementación de JAR en AWS Lambda

Tiene dos opciones para implementar su código en Lambda:

  • Implementación mediante AWS Serverless Application Repository (recomendado)

  • Creación de una función Lambda desde el archivo JAR

Opción 1: Implementación en AWS Serverless Application Repository

Al implementar el archivo JAR en AWS Serverless Application Repository, se crea un archivo YAML de plantilla AWS SAM que representa la arquitectura de la aplicación. A continuación, especifique este archivo YAML y un bucket de Amazon S3 donde los artefactos de su aplicación se carguen y estén disponibles para el AWS Serverless Application Repository. El siguiente procedimiento utiliza el script publish.sh ubicado en el directorio athena-query-federation/tools del SDK de Athena Query Federation que clonó anteriormente.

Para obtener más información y requisitos, consulte Publicación de aplicaciones en la Guía para desarrolladores de AWS Serverless Application Repository, Conceptos de plantillas de AWS SAM en la Guía para desarrolladores de AWS Serverless Application Model y Publicación de aplicaciones sin servidor mediante la CLI de AWS SAM.

En el ejemplo siguiente se muestran los parámetros de un archivo YAML. Agregue parámetros similares a su archivo YAML y guárdelo en su directorio de proyecto. Consulte athena-udf.yaml en GitHub para ver un ejemplo completo.

Transform: 'AWS::Serverless-2016-10-31' Metadata: 'AWS::ServerlessRepo::Application': Name: MyApplicationName Description: 'The description I write for my application' Author: 'Author Name' Labels: - athena-federation SemanticVersion: 1.0.0 Parameters: LambdaFunctionName: Description: 'The name of the Lambda function that will contain your UDFs.' Type: String LambdaTimeout: Description: 'Maximum Lambda invocation runtime in seconds. (min 1 - 900 max)' Default: 900 Type: Number LambdaMemory: Description: 'Lambda memory in MB (min 128 - 3008 max).' Default: 3008 Type: Number Resources: ConnectorConfig: Type: 'AWS::Serverless::Function' Properties: FunctionName: !Ref LambdaFunctionName Handler: "full.path.to.your.handler. For example, com.amazonaws.athena.connectors.udfs.MyUDFHandler" CodeUri: "Relative path to your JAR file. For example, ./target/athena-udfs-1.0.jar" Description: "My description of the UDFs that this Lambda function enables." Runtime: java8 Timeout: !Ref LambdaTimeout MemorySize: !Ref LambdaMemory

Copie el script publish.sh en el directorio del proyecto donde guardó el archivo YAML y ejecute el siguiente comando:

./publish.sh MyS3Location MyYamlFile

Por ejemplo, si la ubicación del bucket es s3://mybucket/mysarapps/athenaudf y el archivo YAML se guardó como my-athena-udfs.yaml:

./publish.sh mybucket/mysarapps/athenaudf my-athena-udfs
Para crear una función Lambda
  1. Abra la consola de Lambda en https://console.aws.amazon.com/lambda/, elija Create function (Crear función), y luego elija Browse serverless app repository (Explorar el repositorio de aplicaciones sin servidor).

  2. Elija Private applications (Aplicaciones privadas) busque su aplicación en la lista o búsquela con palabras clave y selecciónela.

  3. Revise y proporcione los detalles de la aplicación y, a continuación, elija Deploy (Implementar).

    Ahora puede utilizar los nombres de los métodos definidos en su archivo JAR de la función Lambda como UDF en Athena.

Opción 2: creación directa de una función de Lambda

También puede crear una función Lambda directamente mediante la consola o la AWS CLI. En el siguiente ejemplo, se muestra el uso del comando de la CLI create-function de Lambda.

aws lambda create-function \ --function-name MyLambdaFunctionName \ --runtime java8 \ --role arn:aws:iam::1234567890123:role/my_lambda_role \ --handler com.mycompany.athena.udfs.MyUserDefinedFunctions \ --timeout 900 \ --zip-file fileb://./target/my-athena-udfs-1.0-SNAPSHOT.jar