본문 바로가기
일/aws

AWS Glue 활용기 #4 :: Glue Crawler 트러블 슈팅 2/2

by blair2dev 2022. 5. 1.

이전 포스팅 의 결과에 따라 특정 칼럼을 활용하여 버전을 파티셔닝 하고 각각 자동으로 테이블을 생성 하기로 하였다. 

ai 팀에서 api_version 이라는 칼럼에 스키마 버전을 표기해 주기로 하였다.

  1. 해당 칼럼으로 파티셔닝 (spark streaming 코드 수정)
  2. 해당 칼럼 위치 기준 단일 스키마 크롤링
    1. 크롤러가 칼럼의 값 마다 테이블 생성 함
  3. ai 팀에서 버전 표기를 놓친 경우(실수로)
    1.  이러한 경우에만 아래 방법을 적용한다.
      1. 수동 athena DDL 로 새로운 테이블 따로 생성 헤서 바뀐 스키마로 조회가 가능 하도록 한다.

      2. 크롤러에 스키마 변경 옵션 "새 열만 추가"로 바꾼다.
      3. 새로운 테이블로 조회한다.
      4. 다시 스키마 변경되는 경우에 복구한다.
CREATE EXTERNAL TABLE `TableName`(
  `field1` bigint,
  `api_version` string,
  `field2` string,
  `extend` struct<category:array<struct<name:string>>,collections:array<struct<collection:string,id:string,fieldarr:
struct<field:string,field:string,field:string>,field:string>>,field:array<string>,field:string,name:string,
field:string>)
PARTITIONED BY (
  `api_version` string,
  `field1` string,
  `field2` string,
  `year` string,
  `month` string,
  `day` string)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  's3://@@@@@@'
TBLPROPERTIES (
  'CrawlerSchemaDeserializerVersion'='1.0',
  'CrawlerSchemaSerializerVersion'='1.0',
  'UPDATED_BY_CRAWLER'='crawlername',
  'averageRecordSize'='260',
  'classification'='parquet',
  'compressionType'='none',
  'objectCount'='83',
  'recordCount'='248661',
  'sizeKey'='49089304',
  'typeOfData'='file')

 

ALTER TABLE TableName ADD PARTITION (api_version = '1', field = '22', year = '2022', month ='3', day = '25') LOCATION 's3://@@@@/year=2022/month=3/day=25/'

 

api_version 필드 파티셔닝에 따른 glue crawler 의 테이블 분리 생성 A/B test

 

1. 가설 : api_version field 의 value 를 통해 스키마를 구분하고 partitioning 하여 glue crawler를 돌리면 스키마 버전에 따라 테이블이 구분 되어 생성 될 것 이다.

2. test 설계

통제 변인 : earliest, consumer group 변경, 10분 가량 컨슘.

 a. [A test] api_version =1 고정, partitioning 안한 채로 test

  1. av_test_field 없는 채로 적재 (적재 완료)
    1. 크롤링 -> (av_test_a 테이블 정상 생성 확인)
    2.  athena 조회
      1. 정상 이어야 한다. (select * from av_a_test; 쿼리 조회 정상 확인)
  2. av_test_field 추가한 채로 적재 (컨슈머 그룹 변경, earliest) (적재완료)
    1. 크롤링 -> (완료)
    2. athena 조회
        1. 스키마가 충돌 돼서 에러나야 한다. (에러안나고 필드가 추가... 이전 데이터는 스키마가 추가 된 채로 value 는 null 로 되었다 ᅲᅲ)
  3. 위 에서 필드 추가는 스키마 에러에 관여하지 않는 다는 것을 확인 하였다.
    따라서 필드 타입을 바꾸어서 테스트 해본다. av_test_field 를 1 -> “1” 로변경하여 적재해보겠음. (아... 실수로 api_version을 “1” 로 했다... 하지만 상관 없음.)
    1. 크롤러 -> 완료
    2. 드디어 에러가 떳다
      1. a. HIVE_BAD_DATA: Field api_version's type INT64 in parquet file s3://@@@@/av_a_test /topic=@@@@/action=I/platform=APP/year=2022/month=4/day=5/part- 00051-06f5228f-6e8d-494f-a555-56deae5f7f65.c000.snappy.parquet is incompatible with type varchar defined in table schema

b. [B test] partitioning 하고 새로운 path에 api_version 변경 하며 test

  •  av_test_field integer 이고, api_version=1 인 채로 적재 (적재 완료)
    • 크롤링
    • athena 조회
      • 정상 이어야 한다. (api_version_1 이라는 테이블이 아래와 같이 잘 만들어졌다. 쿼리도 정상 조회 된다. 
  • i. av_test_field string 이고, api_version=2 인 채로 적재
    • path에 partitioning이 잘 되었는 지 확인(아래와 같이 정상 partitioning 되었다)
  • 크롤링 (크롤링 성공)
  • athena 조회
    • api_version에 따라 테이블이 잘 만들어 졌는 지 확인 (아래와 같이 잘 만들어 졌다.)
  1. 테이블 마다 쿼리 잘 먹히는 지 확인 (잘 먹힘)
  2. 스키마 인식 각각 잘 되었는지 확인
    1. 아래와 같이 av_test_field 가 각각의 데이터 타입으로 잘 인식 되었다.

1. 결론
      a. 가설이 증명 되었다. 특정 필드를 스키마 버전 기준으로 사용하고 그 필드를 파티셔닝해서 각각 테이블을 만들면 빈번한 현업의 스키마 변경 이슈
를 해소할 수 있을 것이다.

통제변인 : 크롤러 설정

1. A test setting

 
 

2. B test setting