기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
사용자 정의 함수를 사용한 쿼리(미리 보기)
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
예 – 문자열 압축 및 압축 해제
압축
다음 예제에서는 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
이 단원의 단계에서는 명령줄 및 배포에서 Apache Maven
Maven을 사용하여 Athena에 대한 사용자 지정 UDF를 만드는 단계
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 빌드 도구가 설치된 개발 머신에서 작업하는 경우 이 단계를 건너뛸 수 있습니다.
-
복제할 때 생성한
aws-athena-query-federation
디렉터리의 루트에서 개발 환경을 준비하는 prepare_dev_env.sh스크립트를 실행합니다. -
을 업데이트하여 설치 프로세스에서 생성된 새 변수를 소싱하거나 터미널 세션을 다시 시작합니다.
source ~/.profile
중요 이 단계를 건너뛰면 나중에 AWS CLI 함수를 게시할 수 없는 AWS SAM 또는 Lambda 빌드 도구에 대한 오류가 발생합니다.
Maven 프로젝트 만들기
다음 명령을 실행하여 Maven 프로젝트를 만듭니다. Replace groupId
(조직의 고유 ID 사용)을 my-athena-udf
애플리케이션 이름이 있는 Apache Maven 설명서의
mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DgroupId=
groupId
\ -DartifactId=my-athena-udfs
Maven 프로젝트에 종속성 및 플러그인 추가
Maven 프로젝트 pom.xml
파일에 다음 구성을 추가합니다. 예제는 의
<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에 대한 두 개의 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 파일이 프로젝트 target
의
폴더에 생성됩니다.artifactId
-version
.jarartifactId
은 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/tools
publish.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 파일에 유사한 파라미터를 추가하고 프로젝트 디렉터리에 저장합니다. 전체 예제는 의
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 함수를 만들려면
-
lambda/Lambda에서 콘솔을 열고 https://console.aws.amazon.com/함수 생성
을 선택한 다음 서버리스 앱 리포지토리 찾아보기를 선택합니다. -
프라이빗 애플리케이션을 선택하거나 목록에서 애플리케이션을 찾거나 키워드를 사용하여 애플리케이션을 검색한 다음 선택합니다.
-
애플리케이션 세부 정보를 검토하고 제공한 다음 배포를 선택합니다.
이제 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
\ --handlercom.mycompany.athena.udfs.MyUserDefinedFunctions
\ --timeout 900 \ --zip-file fileb://./target/my-athena-udfs-1.0-SNAPSHOT.jar