Background

새벽 시간대 배치는 Oracle 원천 데이터를 Glue 를 통해 parquet 형태로 s3 에 떨구고 Redshift staging 테이블에 랜딩한 뒤, target 테이블에서 겹치는 데이터를 지우고 다시 적재하는 방식으로 돌아간다.

특히 KST 자정 근처에 실행되는 주문 테이블 작업은 시간대 데이터를 빨리 반영해야 한다. 지연이 길어지면 후속 배치와 데이터 신선도에 바로 영향이 간다. (서비스에 사용하는 테이블로 어느 시간대에도 지연이 발생하지 않아야한다..)

이번 디버깅은 자정 실행 건이 평소보다 훨씬 오래 걸리면서 시작됐다. Airflow task는 정상 종료됐지만 전체 수행 시간이 너무 길었다. Airflow queue 문제인지, Redshift WLM queue인지, S3 COPY인지, DELETE 쿼리인지, 아니면 같은 시간대의 Redshift 부하인지 나눠서 확인해야 했다.

Problem

여기에 외부 부하도 겹쳤다. 같은 시간대에 엄청나게 큰 materialized view auto refresh가 돌고 있었다. 이 작업은 매번 full recompute 형태로 실행되며 수십 TB를 스캔했다(심지어 미사용 테이블이었다..). 그래서 ODS delete 쿼리 plan 하나의 문제라기보다, 장시간 대용량 scan과 겹치면서 Redshift storage/I/O 경합이 커진 상황으로 봤다.

Action

다음 순서로 문제를 좁혔다.

  1. Airflow task 로그와 Redshift query 이력을 비교해 실제로 오래 걸린 구간을 찾았다.
  2. stl_wlm_query로 WLM queue 대기 여부를 확인했다.
  3. svl_query_summary, stl_scan, svl_query_report를 통해 scan bytes, row count, slice별 처리량을 확인했다.
  4. target table scan에서 range-restricted scan이 사용됐는지 확인했다.
  5. 같은 시간대에 실행 중이던 장시간 Redshift query와 materialized view refresh 이력을 확인했다.

그 결과 MV 의 auto refresh가 핵심 적재 시간대와 겹치는 것이 가장 큰 리스크로 보였다. 해당 materialized view는 자동 refresh 때마다 full recompute를 반복했고, 사용 패턴에 비해 운영 클러스터에 주는 scan 부하가 컸다.

조치로 auto refresh를 비활성화하고, 필요하다면 off-peak 시간대에 명시적으로 refresh하는 방향을 검토했다.

ALTER MATERIALIZED VIEW {schema}.{table_name} AUTO REFRESH NO;

delete 쿼리는는 ORDER_DTM 조건을 유지했다. 이번 조사에서 해당 조건이 실제로 pruning을 유도한다는 점이 확인됐기 때문이다. 대신 staging 데이터의 order_dtm 범위가 과도하게 넓어지는 경우를 감지할 수 있도록 staging row count, order_dtm span, delete duration, scan bytes를 함께 모니터링하기로 했다.

Outcome

조치 후 새벽 시간대 배치 작업(주문 테이블의 delete insert 쿼리)의 평균 수행 시간은 기존 8-9분대에서 4-5분대로 줄었다.

Aftermath & Lessons Learned

References