Amazon Redshift 는 페타바이트급 컬럼형 MPP(Massively Parallel Processing) 데이터웨어하우스다. 클러스터는 리더 노드 하나와 여러 컴퓨트 노드로 구성된다.
클라이언트(SQL) ──► 리더 노드 : 파싱 · 실행 계획 · 결과 취합 │ ┌───────────────┼───────────────┐ 컴퓨트 노드 1 컴퓨트 노드 2 컴퓨트 노드 3 [슬라이스][슬라이스] ... ← 슬라이스 = 병렬 처리의 최소 단위
리더 노드는 쿼리를 계획해 컴퓨트 노드에 나눠 주고, 돌아온 중간 결과를 합친다.
각 컴퓨트 노드는 여러 슬라이스로 나뉜다. 테이블의 행은 슬라이스에 나뉘어 저장되고, 슬라이스마다 자기 몫을 동시에 처리한다.
저장은 컬럼 단위다. 컬럼 하나의 값들이 1MB 블록에 모여 압축되므로 "수억 행에서 컬럼 몇 개만 집계"하는 쿼리가 빠르다.
💡 관련 이론: MPP 의 성능은 가장 느린 슬라이스가 정한다. 모든 슬라이스가 끝나야 쿼리가 끝나기 때문이다. 한 슬라이스에 데이터가 몰리면(스큐) 나머지 슬라이스가 놀고 있어도 쿼리는 그 슬라이스를 기다린다. 분산 키 설계의 목표는 "고르게 나누되, 조인할 행끼리는 같은 곳에"다.
-- KEY 분산: 지정 컬럼의 값이 같으면 같은 슬라이스에 배치CREATE TABLE orders ( order_id BIGINT, customer_id BIGINT, amount DECIMAL(12,2))DISTSTYLE KEYDISTKEY (customer_id);-- ALL 분산: 테이블 전체를 모든 노드에 복제 (작은 차원 테이블용)CREATE TABLE dim_region (region_id INT, region_name VARCHAR(50))DISTSTYLE ALL;-- EVEN 분산: 라운드로빈으로 균등 분배 (조인 키가 명확치 않을 때)CREATE TABLE event_log (event_id BIGINT, payload VARCHAR(2000))DISTSTYLE EVEN;
스타일
배치 방식
맞는 경우
치르는 값
AUTO(기본)
작을 때 ALL 로 시작, 커지면 KEY(기본 키 등 적합한 컬럼) 또는 EVEN 으로 자동 변경
대부분의 테이블
직접 제어하지 않음
KEY
한 컬럼의 값이 같으면 같은 슬라이스
큰 테이블끼리 같은 키로 자주 조인
값이 편향되면 스큐
ALL
모든 노드에 전체 사본
작고 자주 바뀌지 않는 차원 테이블
저장량이 노드 수만큼 곱해지고 적재·갱신이 느려짐
EVEN
컬럼 값과 무관하게 라운드로빈
조인에 참여하지 않거나 KEY·ALL 을 고르기 애매할 때
조인 시 재분배
조인에서 벌어지는 일이 분산 스타일을 고르는 기준이다.
두 테이블이 같은 컬럼을 DISTKEY 로 가지면 조인할 행이 이미 같은 슬라이스에 있다. 네트워크로 행을 옮기지 않는 코로케이티드 조인이 된다.
한쪽이 ALL 이면 모든 노드에 사본이 있으므로 역시 옮길 것이 없다.
그 외에는 조인 직전에 한쪽(또는 양쪽) 테이블의 행을 조인 키 기준으로 슬라이스 사이에 다시 뿌린다. EXPLAIN 에서 DS_DIST_NONE·DS_DIST_ALL_NONE 은 재분배 없음, DS_BCAST_INNER(안쪽 테이블을 전 노드로 복사)·DS_DIST_BOTH(양쪽 재분배)는 비용이 큰 신호다.
DISTKEY 는 테이블당 컬럼 하나다. 여러 테이블과 조인하는 팩트 테이블은 가장 크고 가장 자주 조인하는 상대의 키를 고르고, 나머지 작은 차원은 ALL 로 둔다.
ALL 은 "작은 테이블"보다 "천천히 변하는 테이블" 에 맞는 선택이다. 쓰기가 노드 수만큼 반복되기 때문이다. 공식 문서는 아주 작은 차원 테이블은 쿼리 중 재분배 비용이 원래 낮아 ALL 의 이득이 크지 않다고도 적는다. 시험에서는 "작은 차원 테이블 + 조인 재분배 제거 = ALL"로 묻는다.
AUTO 가 스타일을 바꾸는 작업은 백그라운드에서 일어난다.
⚠️ 함정: DISTKEY 를 조인 키라는 이유만으로 고르면 스큐가 난다. 값이 몇 개뿐이거나(status, country) 한 값에 행이 몰린 컬럼(NULL 이 대부분인 컬럼, 한 대형 고객이 주문의 절반을 차지하는 customer_id)은 한 슬라이스를 무겁게 만든다. SVV_TABLE_INFO 의 skew_rows 가 크면 키를 바꾸거나 EVEN 으로 간다.
-- 테이블별 분산 스타일, 정렬 키, 스큐, 미정렬 비율 확인SELECT "table", diststyle, sortkey1, skew_rows, unsorted, stats_offFROM svv_table_infoORDER BY skew_rows DESC;
-- Spectrum 외부 스키마 + S3 데이터와 내부 테이블 조인CREATE EXTERNAL SCHEMA spectrum_extFROM DATA CATALOG DATABASE 'datalake_db'IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftSpectrumRole';SELECT d.region, SUM(s.amount)FROM spectrum_ext.raw_events s -- S3 의 외부 테이블JOIN dim_region d ON s.region_id = d.region_id -- Redshift 내부 테이블WHERE s.dt = '2026-06-26' -- 외부 테이블의 파티션 컬럼 → 프루닝GROUP BY d.region;
외부 테이블의 정의는 Glue Data Catalog(또는 Hive 메타스토어)에 있다. Athena 가 쓰는 테이블을 그대로 쓴다.
조건 필터링과 집계 같은 무거운 작업은 클러스터와 별개인 Spectrum 계층으로 내려가 처리된다. 클러스터 자원을 적게 쓰고, 여러 클러스터가 같은 S3 데이터를 사본 없이 조회한다.
과금은 스캔한 바이트 기준이다(쿼리당 최소 10MB). 그래서 Athena 와 똑같이 파티션·Parquet·압축이 곧 비용이다.
외부 테이블은 읽기 전용이다. UPDATE 같은 변경은 지원하지 않는다.
클러스터와 버킷은 같은 리전이어야 한다.
핫 데이터는 Redshift 에, 오래된 대용량 이력은 S3 + Spectrum 에 두고 뷰로 합쳐 보는 것이 레이크하우스 패턴이다.
수동 WLM 의 기본 큐는 동시 실행 5 로 시작한다. 슬롯을 늘리면 슬롯당 메모리가 줄어, 메모리 안에서 끝나던 쿼리가 디스크에 중간 결과를 쓰며 느려진다. "동시성을 올렸더니 더 느려졌다"의 원인이다.
쿼리는 사용자 그룹이나 쿼리 그룹 레이블(SET query_group TO 'critical_dashboards';)로 큐에 배정된다.
쿼리 모니터링 규칙(QMR): 실행 시간·스캔 행 수 같은 지표가 임계를 넘는 쿼리를 기록(log)·중단(abort)하거나, 수동 WLM 에서는 다른 큐로 이동(hop), 자동 WLM 에서는 우선순위를 변경한다. 폭주 쿼리 방어 장치다. 큐 단위 WLM 타임아웃은 더 이상 권장되지 않고 QMR 로 대체한다.
SQA(Short Query Acceleration): 짧게 끝날 쿼리를 긴 쿼리 뒤에 줄 세우지 않고 먼저 처리한다. 짧은 쿼리 전용 큐를 따로 만들 필요가 없어진다.
동시성 스케일링은 큐에 쿼리가 쌓이면 임시 클러스터를 자동으로 붙여 대기 중인 쿼리를 그쪽에서 돌린다.
WLM 큐의 동시성 스케일링 모드를 auto 로 켠다. 붙일 수 있는 클러스터 수는 max_concurrency_scaling_clusters(기본 1)로 정한다.
읽기 쿼리뿐 아니라 COPY·INSERT·DELETE·UPDATE·CTAS 같은 쓰기 작업도 지원한다(쓰기는 RA3 계열에서만).
과금은 임시 클러스터가 실제로 쿼리를 돌린 시간만, 초 단위다. 메인 클러스터가 하루 가동되면 1시간의 무료 크레딧이 쌓이고 최대 30시간까지 누적된다. 그래서 하루 한 번 짧게 몰리는 피크는 대개 추가 비용 없이 흡수된다.
받지 못하는 쿼리: INTERLEAVED 정렬 키 테이블, 임시 테이블, Python·Lambda UDF 를 쓰는 쿼리, DISTSTYLE ALL 테이블에 대한 쓰기 등.
동시성 스케일링은 "스토리지와 메인 클러스터는 그대로 두고 처리 용량만 잠깐 빌리는" 모델이다. 매일 아침 대시보드 갱신처럼 짧고 주기적인 폭증에 맞는다. 하루 종일 큐가 차 있다면 그것은 폭증이 아니라 용량 부족이므로 클러스터를 키우거나(리사이즈) 쿼리·키 설계를 고쳐야 한다.