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
Para ver un ejemplo del uso de UDF para ampliar las consultas geoespaciales en Amazon Athena, consulteAmplíe las consultas geoespaciales en Amazon Athena con UDF yAWS Lambda
Condiciones y limitaciones
-
Funciones Athena integradas— Las funciones integradas en Athena están diseñadas para ofrecer 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 depackage.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 UDF requieren parámetros— Los métodos UDF deben tener al menos un parámetro de entrada. Al intentar invocar una UDF definida sin parámetros de entrada, se produce una excepción de tiempo de ejecución. Las UDF están diseñadas para realizar funciones en registros de datos, pero una UDF sin argumentos no admite 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— Los UDF no admiten el filtrado a nivel de fila de Lake Formation.
-
Vistas: no se pueden utilizar vistas con UDF.
-
Problemas conocidos— Para la mayoríaup-to-datelista de problemas conocidos, consulteLimitaciones y problemas
en los pasajeros/aws-athena-query-federationsección deGitHub.
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. Usa Athena sin elAmazonAthenaPreviewFunctionality
grupo de trabajo.
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
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 Lambda, puede utilizar el ARN de Lambda. En escenarios con 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. Cadavariable data_type
especifica una variable con nombre con su tipo de datos correspondiente, que la UDF acepta como entrada. Eldata_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 datosDECIMAL
, utilice la sintaxisRETURNS DECIMAL(
dondeprecision
,scale
)precision
yscale
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 unaexpression
(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áusulaUSING EXTERNAL FUNCTION
.
Ejemplos
Por ejemplo, consultas basadas en laAthenaUDFHandler.java
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 delUserDefinedFunctionHandler.java
Los pasos de esta sección muestran cómo escribir y crear un archivo Jar de UDF personalizado mediante Apache Maven
Pasos para crear una UDF personalizada para Athena mediante Maven
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.
-
Desde la raíz del directorio
aws-athena-query-federation
que creó cuando realizó la clonación, ejecute el script prepare_dev_env.shque prepara el entorno de desarrollo. -
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. ReemplazarID de grupo
con el identificador único de su organización y reemplacemy-athena-udf
con el nombre de su solicitud Para obtener más información, consulte¿Cómo hago mi primer proyecto de 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 lapom.xml
<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
Crea una nueva clase extendiendoUserDefinedFunctionHandler.java
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
, donde artifactId
-version
.jarartifactId
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.shathena-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. Consulteatena-udf.yaml
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
-
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). -
Elija Private applications (Aplicaciones privadas) busque su aplicación en la lista o búsquela con palabras clave y selecciónela.
-
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
\ --handlercom.mycompany.athena.udfs.MyUserDefinedFunctions
\ --timeout 900 \ --zip-file fileb://./target/my-athena-udfs-1.0-SNAPSHOT.jar