우리는 지난 포스트에서 왜 Athena를 써야 하며, 무슨 혜택이 있는지 알아보았습니다.
이제 간단한 예제와 Access Log를 분석해 보도록 합시다.

이 포스트는 AWS ELB의 기본 경로 규칙을 따르고 있습니다

데이터베이스 및 테이블 생성하기

/*
데이터베이스 생성
*/
create database alb_db
/*
테이블 생성

참고로 현재시간(2020년 3월 2일) 이후로 AWS에 의해 스키마 정보가 업데이트될 수 있으니 테이블 생성 시 아래 링크를 참고하시면 더 좋습니다.

https://docs.aws.amazon.com/athena/latest/ug/application-load-balancer-logs.html
*/
CREATE EXTERNAL TABLE IF NOT EXISTS alb_logs (
            type string,
            time string,
            elb string,
            client_ip string,
            client_port int,
            target_ip string,
            target_port int,
            request_processing_time double,
            target_processing_time double,
            response_processing_time double,
            elb_status_code string,
            target_status_code string,
            received_bytes bigint,
            sent_bytes bigint,
            request_verb string,
            request_url string,
            request_proto string,
            user_agent string,
            ssl_cipher string,
            ssl_protocol string,
            target_group_arn string,
            trace_id string,
            domain_name string,
            chosen_cert_arn string,
            matched_rule_priority string,
            request_creation_time string,
            actions_executed string,
            redirect_url string,
            lambda_error_reason string,
            new_field string
            )
            PARTITIONED BY(year string, month string, day string) 
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' = 
        '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) /"([^ ]*) ([^ ]*) (- |[^ ]*)/" /"([^/"]*)/" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) /"([^/"]*)/" /"([^/"]*)/" /"([^/"]*)/" ([-.0-9]*) ([^ ]*) /"([^/"]*)/" /"([^/"]*)/"($| /"[^ ]*/")(.*)')
            LOCATION 's3://your-alb-logs-directory/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<REGION>/';

잘 보시면 중간에 PARTITIONED BY(year string, month string, day string)이 추가되어 있습니다.

이를 추가하지 않는다면 우리는 번거롭게 파티션 추가할 필요 없이 모든 데이터를 즉시 쿼리 가능합니다.
데이터가 얼마 없다면 이는 매우 유용하겠지만 만약 로그가 엄청나게 많이 있다면?
돈도 많이 내고 쿼리 시간도 엄청나게 오래 걸리게 되죠.

데이터 파티셔닝

파티셔닝은 우리가 사용할 S3 bucket의 폴더를 특정해주며, 쿼리 시 해당 폴더의 로그만 스캔하게 해줍니다.
전체 데이터를 스캔하지 않으며 이로써 우리는 쿼리에 들어가는 비용과 시간을 절약할 수 있습니다.

하루의 1~2기가 정도의 로그를 쌓고 있으므로 우리의 경우 (year, month, day) 파티션을 사용하여 일별로 파티션을 관리하고 있습니다만, 만약 특정 서비스의 access 로그가 많지 않다면 파티션을 (year, month)까지만 설정하시는 것도 좋은 방법입니다.

-- 아래는 alb_logs 테이블에 하나의 파티션을로드하는 샘플 "alter table" 명령입니다.
-- 스캔하고 싶은 year, month, day를 bucket의 폴더명과 동일하게 입력하고, location에 정확한 S3 경로를 입력해줍니다.
ALTER TABLE alb_logs add PARTITION (year="2020", month="01", day="01") location "s3://your-alb-logs-directory/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<REGION>/2020/01/01";

-- 아래 명령어로 불필요한 파티션을 제거 할 수 있습니다.
-- 이것저것 추가하여 정리가 너무 귀찮다면 DROP TABLE 후 다시 생성하는 것도 좋은 방법입니다. 
ALTER TABLE alb_logs DROP PARTITION (year="2020", month="01", day="01");

-- 테이블에 현재 추가되어있는 파티션들을 볼 수 있습니다.
SHOW PARTITIONS alb_logs;

-- 파티션 데이터 불러오기 명령어입니다
-- 파티션은 추가될 때 데이터를 불러옵니다. 하지만 최신데이터를 보고 싶을 경우 아래 명령어를 이용해 데이터를 업데이트 할 수 있습니다.
-- 이 명령은 로드할 파티션 수에 따라 실행하는 데 시간이 걸릴 수 있습니다.
MSCK REPAIR TABLE alb_logs;

데이터 쿼리 하기

SELECT * FROM alb_logs limit 10;

과정을 잘 따라왔다면 위 명령어를 통해 10개의 데이터를 확인해 볼수 있습니다.

파티션을 추가해서 사용할 경우 검색 속도가 비약적으로 빨라진 걸 느끼실 수 있습니다.
뿐만 아니라 아래 링크의 10가지 성능 향상 팁 및 쿼리 최적화를 통해 더욱더 빠른 속도로 원하는 결과를 받아볼 수 있습니다.

Example Queries for ALB Logs

Athena를 사용하여 Load Balancer 액세스 로그 분석

Amazon Athena – 10가지 성능 향상 팁 | Amazon Web Services 한국 블로그

참고

Amazon Athena(이)란 무엇입니까?

Athena를 사용하여 Load Balancer 액세스 로그 분석

Example Queries for ALB Logs

Amazon Athena – 10가지 성능 향상 팁 | Amazon Web Services 한국 블로그

Amazon Athena 요금 – Amazon Web Services(AWS)

Amazon Athena 테이블 파티셔닝

마치며

수동으로 파티션을 관리하기 전에 먼저 S3폴더와 파티션 자동 매치 기능이 있다고 해서 시도했었습니다.
또한 AWS glue라는 서비스를 통해 배치를 등록해 테이블의 파티션을 동적 생성해줄 수도 있습니다. 하지만 제가 glue로 테이블을 만들면 파티션을 제대로 못 불러오더랬죠.
결국 어느 방법도 제대로 되지 않았고 현재는 로그 분석이 필요할 경우 수동으로 파티션을 등록해서 사용하는 중입니다.

파티션 등록 자동화할 수 있는 방법 있으면 댓글 부탁드릴게요!