사용자 정의 함수를 사용한 쿼리(미리 보기) - Amazon Athena

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

사용자 정의 함수를 사용한 쿼리(미리 보기)

Amazon Athena의 사용자 정의 함수(UDF)를 사용하면 사용자 지정 함수를 만들어 레코드 또는 레코드 그룹을 처리할 수 있습니다. UDF는 파라미터를 수락하고 작업을 수행한 다음 결과를 반환합니다.

Athena에서 UDF를 사용하려면 SQL 쿼리의 USING FUNCTION 문 앞에 SELECT 절을 작성합니다. SELECT 문은 UDF를 참조하고 쿼리가 실행될 때 UDF에 전달되는 변수를 정의합니다. SQL 쿼리는 UDF를 호출할 때 Java 런타임을 사용하여 Lambda 함수를 호출합니다. UDFs는 Lambda 함수 내에서 Java 배포 패키지의 메서드로 정의됩니다. 함수에 대해 동일한 Java 배포 패키지에 여러 UDFs를 정의할 수 있습니다.Lambda 또한 Lambda 절에 USING FUNCTION 함수의 이름을 지정합니다.

Lambda에 대한 Athena 함수를 배포하기 위한 두 가지 옵션이 있습니다.UDFs 를 사용하여 함수를 직접 배포하거나 Lambda를 사용할 수 있습니다.AWS Serverless Application Repository 에 대한 기존 Lambda 함수를 찾으려면 퍼블릭 UDFs 또는 프라이빗 리포지토리를 검색한 다음 AWS Serverless Application Repository에 배포하면 됩니다.Lambda Java 소스 코드를 생성 또는 수정하고 JAR 파일로 패키지하고 Lambda 또는 AWS Serverless Application Repository.을 사용하여 배포할 수도 있습니다. 시작하기 위해 예제 Java 소스 코드 및 패키지를 제공합니다. 에 대한 자세한 내용은 Lambda 단원을 참조하십시오.AWS Lambda Developer Guide AWS Serverless Application Repository에 대한 자세한 내용은 AWS Serverless Application Repository 개발자 안내서. 단원을 참조하십시오.

고려 사항 및 제한

  • 사용 가능한 리전 – Athena UDF 기능은 미국 동부(버지니아 북부), 아시아 태평양(뭄바이), 유럽(아일랜드), 및 미국 서부(오레곤) 리전에서 미리 보기로 사용할 수 있습니다.

  • AmazonAthenaPreviewFunctionality 작업 그룹 – To use this feature in preview, you must create an Athena workgroup named AmazonAthenaPreviewFunctionality and join that workgroup. For more information, see 작업 관리.

  • 기본 제공 Athena 함수 – Athena의 기본 제공 Presto 함수는 고성능으로 설계되었습니다. 가능하면 UDFs를 통해 내장 함수를 사용하는 것이 좋습니다. 기본 제공 함수에 대한 자세한 내용은 단원을 참조하십시오.의 Presto 함수Amazon Athena.

  • 스칼라 UDFs만 해당 – Athena는 한 번에 한 행을 처리하고 단일 열 값을 반환하는 스칼라 UDFs만 지원합니다. Athena는 Lambda를 호출할 때마다 UDF에 행 배치를 병렬로 전달합니다. 및 쿼리를 설계할 때는 이 처리 설계가 가질 수 있는 네트워크 트래픽에 미칠 수 있는 영향을 염두에 두어야 합니다.UDFs

  • Java 런타임 전용 – 현재 Athena는 UDFs에 Java 8 런타임만 지원합니다.Lambda

  • IAM 권한 – Athena에서 UDF 쿼리 문을 포함하는 쿼리를 실행하고 UDF 문을 만들려면 쿼리를 실행하는 IAM 보안 주체가 Athena 함수 외에 작업을 수행할 수 있어야 합니다. 자세한 내용은 단원을 참조하십시오.Amazon Athena User Defined Functions (UDF)를 허용할 IAM 권한 정책 예제.

  • Lambda 할당량 – Lambda 할당량이 UDFs에 적용됩니다. 자세한 내용은 AWS Lambda의 할당량AWS Lambda Developer Guide을 참조하십시오.

  • 알려진 문제 – 알려진 문제의 최신 목록은 제한 사항 및 문제를 참조하십시오.Athena Federated Query (Preview)

Video

에서 UDFs 사용에 대해 자세히 알아보려면 다음 비디오를 시청하십시오.Athena

동영상: UDFsUDFAmazon Athena)

다음 비디오는 UDFs에서 Amazon Athena를 사용하여 민감한 정보를 삭제하는 방법을 보여줍니다.

UDF 쿼리 구문

절은 쿼리의 후속 USING FUNCTION 문에서 참조할 수 있는 UDF 또는 여러 UDFs를 지정합니다.SELECT UDF의 메서드 이름과 UDF를 호스팅하는 Lambda 함수의 이름이 필요합니다.

Synopsis

USING FUNCTION UDF_name(variable1 data_type[, variable2 data_type][,...]) RETURNS data_type TYPE LAMBDA_INVOKE WITH (lambda_name = 'my_lambda_function')[, FUNCTION][, ...] SELECT [...] UDF_name(expression) [...]

Parameters

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

UDF_name 는 참조된 Lambda 함수 내의 Java 메서드에 해당하는 UDF의 이름을 지정합니다. 각각 variable data_type 는 UDF가 입력으로 수락할 수 있는 해당 데이터 유형과 함께 명명된 변수를 지정합니다. 지정 data_type 다음 표에 나열된 지원되는 Athena 데이터 유형 중 하나인 . 데이터 유형은 해당 Java 데이터 유형에 매핑해야 합니다.

Athena 데이터 형식 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

java.math.BigDecimal

BIGINT

java.lang.Long

INTEGER

java.lang.Int

VARCHAR

java.lang.String

VARBINARY

byte[]

BOOLEAN

java.lang.Boolean

ARRAY

java.util.List

ROW

java.util.Map<String, Object>

RETURNS data_type TYPE

data_type은 UDF가 출력으로 반환하는 SQL 데이터 유형을 지정합니다. 위의 표에 나열된 Athena 데이터 유형이 지원됩니다.

LAMBDA_INVOKE WITH(lambda_name = ')my_lambda_function')

my_lambda_function 는 UDF를 실행할 때 호출할 Lambda 함수의 이름을 지정합니다.

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

UDF에 값을 전달하고 결과를 반환하는 SELECT 쿼리입니다. UDF_name는 사용할 UDF와 그 뒤에 값을 전달하기 위해 평가되는 expression를 지정합니다. 전달되고 반환되는 값은 USING FUNCTION 절의 UDF에 대해 지정된 해당 데이터 유형과 일치해야 합니다.

Examples

다음 예제에서는 UDFs를 사용한 쿼리를 보여줍니다. 쿼리 예제는 Athena의 AthenaUDFHandler.java 코드를 기반으로 합니다.GitHub

예 – 문자열 압축 및 압축 해제

압축

다음 예제에서는 compress라는 Lambda 함수에 정의된 MyAthenaUDFLambda. UDF를 사용하는 방법을 보여줍니다.

USING FUNCTION compress(col1 VARCHAR) RETURNS VARCHAR TYPE LAMBDA_INVOKE WITH (lambda_name = 'MyAthenaUDFLambda') SELECT compress('StringToBeCompressed');

쿼리 결과가 를 반환합니다.ewLLinKzEsPyXdKdc7PLShKLS5OTQEAUrEH9w==.

압축 해제

다음 예제에서는 동일한 decompress 함수에 정의된 Lambda UDF를 사용하는 방법을 보여줍니다.

USING FUNCTION decompress(col1 VARCHAR) RETURNS VARCHAR TYPE LAMBDA_INVOKE WITH (lambda_name = 'MyAthenaUDFLambda') SELECT decompress('ewLLinKzEsPyXdKdc7PLShKLS5OTQEAUrEH9w==');

쿼리 결과가 를 반환합니다.StringToBeCompressed.

을 사용하여 UDF 생성 및 배포Lambda

사용자 지정 UDF를 생성하려면 UserDefinedFunctionHandler 클래스를 확장하여 새 Java 클래스를 생성합니다. SDK의 UserDefinedFunctionHandler.java에 대한 소스 코드는 awslabs/aws-athena-query-federation/athena-federation-sdk GitHub리포지토리에서 사용 가능하며, 사용자 지정 UDF를 생성하기 위해 검사 및 수정할 수 있습니다.https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-udfs

이 단원의 단계에서는 명령줄 및 배포에서 Apache Maven을 사용하여 사용자 지정 UDF Jar 파일을 작성하고 빌드하는 방법을 보여줍니다.

SDK 복제 및 개발 환경 준비

시작하기 전에 git가 를 사용하여 시스템에 설치되어 있는지 확인하십시오.sudo yum install git -y.

AWS 쿼리 연동 SDK를 설치하려면

  • 명령줄에 다음을 입력하여 SDK 리포지토리를 복제합니다. 이 리포지토리에는 SDK, 예제 및 데이터 원본 커넥터 제품군이 포함되어 있습니다. 데이터 원본 커넥터에 대한 자세한 내용은 단원을 참고하십시오.사용 Amazon Athena Federated Query (Preview).

    git clone https://github.com/awslabs/aws-athena-query-federation.git

이 절차의 사전 조건을 설치하려면

이미 Apache Maven, AWS CLI 및 AWS Serverless Application Model 빌드 도구가 설치된 개발 머신에서 작업하는 경우 이 단계를 건너뛸 수 있습니다.

  1. 복제할 때 생성한 aws-athena-query-federation 디렉터리의 루트에서 개발 환경을 준비하는 prepare_dev_env.sh 스크립트를 실행합니다.

  2. 을 업데이트하여 설치 프로세스에서 생성된 새 변수를 소싱하거나 터미널 세션을 다시 시작합니다.

    source ~/.profile
    중요

    이 단계를 건너뛰면 나중에 AWS CLI 함수를 게시할 수 없는 AWS SAM 또는 Lambda 빌드 도구에 대한 오류가 발생합니다.

Maven 프로젝트 만들기

다음 명령을 실행하여 Maven 프로젝트를 만듭니다. Replace groupId (조직의 고유 ID 사용)을 my-athena-udf 애플리케이션 이름이 있는 Apache Maven 설명서의 첫 번째 Maven 프로젝트를 만들려면 어떻게 해야 합니까?를 참조하십시오.

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

Maven 프로젝트에 종속성 및 플러그인 추가

Maven 프로젝트 pom.xml 파일에 다음 구성을 추가합니다. 예제는 pom.xmlGitHub 파일을 참조하십시오.

<properties> <aws-athena-federation-sdk.version>2019.48.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>

용 Java 코드 작성UDFs

UserDefinedFunctionHandler.java를 확장하여 새 클래스를 생성합니다. 클래스 내부에 UDFs를 작성합니다.

다음 예제에서는 UDFs에 대한 두 개의 Java 메서드인 compress()decompress()가 클래스 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); } }

JAR 파일 빌드

mvn clean install을 실행하여 프로젝트를 빌드합니다. 성공적으로 빌드되면 JAR 파일이 프로젝트 targetartifactId-version.jar 폴더에 생성됩니다.artifactId 은 Maven 프로젝트에 제공한 이름입니다(예: my-athena-udfs).

에 JAR 배포AWS Lambda

Lambda에 코드를 배포하는 두 가지 옵션이 있습니다.

  • AWS Serverless Application Repository을 사용하여 배포(권장)

  • JAR 파일에서 Lambda 함수 만들기

옵션 1: 에 배포AWS Serverless Application Repository

AWS Serverless Application Repository에 JAR 파일을 배포할 때 애플리케이션의 아키텍처를 나타내는 AWS SAM 템플릿 YAML 파일을 만듭니다. 그런 다음 이 YAML 파일과 애플리케이션의 아티팩트를 업로드하고 Amazon S3을 사용할 수 있는 AWS Serverless Application Repository. 버킷을 지정합니다. 아래 절차에서는 이전에 복제한 쿼리 연동 SDK의 디렉터리에 있는 athena-query-federation/toolspublish.shAthena 스크립트를 사용합니다.

자세한 내용 및 요구 사항은 https://docs.aws.amazon.com/serverlessrepo/latest/devguide/serverlessrepo-publishing-applications.html애플리케이션 게시AWS Serverless Application Repository 개발자 안내서, 의 AWS SAM 템플릿 개념 CLI를 사용하여 서버리스 애플리케이션 게시AWS Serverless Application Model 개발자 안내서를 참조하십시오.AWS SAM

다음 예제에서는 YAML 파일의 파라미터를 보여줍니다. YAML 파일에 유사한 파라미터를 추가하고 프로젝트 디렉터리에 저장합니다. 전체 예제는 athena-udf.yamlGitHub을 참조하십시오.

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

YAML 파일을 저장한 프로젝트 디렉터리에 publish.sh 스크립트를 복사하고 다음 명령을 실행합니다.

./publish.sh MyS3Location MyYamlFile

예를 들어 버킷 위치가 s3://mybucket/mysarapps/athenaudf이고 YAML 파일이 my-athena-udfs.yaml:로 저장된 경우:

./publish.sh mybucket/mysarapps/athenaudf my-athena-udfs

Lambda 함수를 만들려면

  1. lambda/Lambda에서 콘솔을 열고 https://console.aws.amazon.com/함수 생성을 선택한 다음 서버리스 앱 리포지토리 찾아보기를 선택합니다.

  2. 프라이빗 애플리케이션을 선택하거나 목록에서 애플리케이션을 찾거나 키워드를 사용하여 애플리케이션을 검색한 다음 선택합니다.

  3. 애플리케이션 세부 정보를 검토하고 제공한 다음 배포를 선택합니다.

    이제 Lambda에서 UDFs 함수 JAR 파일에 정의된 메서드 이름을 Athena로 사용할 수 있습니다.

옵션 2: 직접 Lambda 함수 만들기

콘솔 또는 Lambda를 사용하여 직접 AWS CLI. 함수를 만들 수도 있습니다. 다음은 Lambda create-function CLI 명령을 사용하는 예제입니다.

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