← Theory 목록으로

Session 6: Amazon Redshift

MPP 아키텍처, 성능 최적화, 데이터 공유, ML

1. Redshift 아키텍처

Amazon Redshift는 페타바이트 규모의 데이터 웨어하우스 서비스입니다. MPP(Massively Parallel Processing) 아키텍처와 컬럼형 저장으로 분석 쿼리에 최적화되어 있습니다.

Redshift 클러스터 아키텍처
┌─────────────────────────────────────────────────────────────────────┐
│                    Redshift Cluster Architecture                     │
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │                      Leader Node                                 ││
│  │  • SQL 파싱 및 쿼리 계획 생성                                    ││
│  │  • 쿼리 분산 및 결과 집계                                        ││
│  │  • 클라이언트 연결 관리                                          ││
│  └──────────────────────────┬──────────────────────────────────────┘│
│                             │                                        │
│           ┌─────────────────┼─────────────────┐                     │
│           ▼                 ▼                 ▼                     │
│  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐       │
│  │  Compute Node 1 │ │  Compute Node 2 │ │  Compute Node N │       │
│  │                 │ │                 │ │                 │       │
│  │ ┌─────┐ ┌─────┐│ │ ┌─────┐ ┌─────┐│ │ ┌─────┐ ┌─────┐│       │
│  │ │Slice│ │Slice││ │ │Slice│ │Slice││ │ │Slice│ │Slice││       │
│  │ │  1  │ │  2  ││ │ │  3  │ │  4  ││ │ │  N  │ │ N+1 ││       │
│  │ └─────┘ └─────┘│ │ └─────┘ └─────┘│ │ └─────┘ └─────┘│       │
│  │                 │ │                 │ │                 │       │
│  │  Local Storage  │ │  Local Storage  │ │  Local Storage  │       │
│  └─────────────────┘ └─────────────────┘ └─────────────────┘       │
│                                                                      │
│  Managed Storage (RA3):                                             │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │                         Amazon S3                                ││
│  │  • 자동 데이터 계층화                                            ││
│  │  • 컴퓨팅과 스토리지 독립 확장                                   ││
│  └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘

Leader Node

  • • 쿼리 파싱 및 최적화
  • • 실행 계획 생성
  • • 결과 집계 및 반환

Compute Node

  • • 실제 데이터 저장
  • • 병렬 쿼리 실행
  • • 슬라이스 단위 처리

1.2 노드 유형

노드 유형 비교
유형스토리지특징사용 사례
RA3Managed (S3)컴퓨팅/스토리지 분리대부분의 워크로드 (권장)
DC2Local SSD고성능, 고정 스토리지1TB 미만, 고성능 필요
DS2Local HDD대용량, 저비용레거시 (RA3 권장)

💡 RA3 권장 이유

RA3는 컴퓨팅과 스토리지를 독립적으로 확장할 수 있어 비용 효율적입니다. 자주 사용하는 데이터는 로컬 SSD에 캐시되어 성능도 우수합니다.

1.3 컬럼형 저장

행 기반 저장 (OLTP)                    컬럼 기반 저장 (OLAP/Redshift)
┌─────────────────────────┐            ┌─────────────────────────┐
│ id │ name  │ amount    │            │ id: 1, 2, 3, 4, 5...    │
├────┼───────┼───────────┤            ├─────────────────────────┤
│ 1  │ Alice │ 100       │            │ name: Alice, Bob, ...   │
│ 2  │ Bob   │ 200       │            ├─────────────────────────┤
│ 3  │ Carol │ 150       │            │ amount: 100, 200, 150...│
└─────────────────────────┘            └─────────────────────────┘

SELECT SUM(amount) FROM orders;

행 기반: 모든 컬럼 읽기 필요         컬럼 기반: amount 컬럼만 읽기
████████████████████████████         ░░░░░░░░░░░░████████████████

장점:
• 필요한 컬럼만 읽어 I/O 감소
• 같은 타입 데이터 연속 → 압축률 향상 (최대 10x)
• 벡터화 처리로 CPU 효율 증가

2. 테이블 설계

2.1 분산키 (DISTKEY)

분산 스타일
┌─────────────────────────────────────────────────────────────────────┐
│                    Distribution Styles                               │
│                                                                      │
│  1. KEY Distribution (DISTKEY)                                       │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐                               │
│  │ Node 1  │ │ Node 2  │ │ Node 3  │                               │
│  │ user=A  │ │ user=B  │ │ user=C  │  같은 키 값 → 같은 노드       │
│  │ user=A  │ │ user=B  │ │ user=C  │  JOIN 시 데이터 이동 최소화   │
│  └─────────┘ └─────────┘ └─────────┘                               │
│                                                                      │
│  2. ALL Distribution (DISTSTYLE ALL)                                │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐                               │
│  │ Node 1  │ │ Node 2  │ │ Node 3  │                               │
│  │ 전체복사│ │ 전체복사│ │ 전체복사│  작은 테이블 전체 복제        │
│  └─────────┘ └─────────┘ └─────────┘  JOIN 시 네트워크 이동 없음   │
│                                                                      │
│  3. EVEN Distribution (DISTSTYLE EVEN)                              │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐                               │
│  │ Node 1  │ │ Node 2  │ │ Node 3  │                               │
│  │ Row 1,4 │ │ Row 2,5 │ │ Row 3,6 │  라운드 로빈 분산             │
│  └─────────┘ └─────────┘ └─────────┘  기본값, JOIN 시 재분산 필요  │
│                                                                      │
│  4. AUTO Distribution                                                │
│  Redshift가 테이블 크기에 따라 자동 선택 (권장)                     │
└─────────────────────────────────────────────────────────────────────┘

// 분산키 설정 예시

-- KEY 분산: 자주 JOIN하는 컬럼
CREATE TABLE orders (
  order_id BIGINT,
  customer_id BIGINT,
  amount DECIMAL(10,2)
)
DISTSTYLE KEY
DISTKEY (customer_id);

-- ALL 분산: 작은 차원 테이블
CREATE TABLE regions (
  region_id INT,
  region_name VARCHAR(50)
)
DISTSTYLE ALL;

-- AUTO 분산: Redshift 자동 결정 (권장)
CREATE TABLE events (
  event_id BIGINT,
  event_type VARCHAR(50)
)
DISTSTYLE AUTO;

2.2 정렬키 (SORTKEY)

정렬키 유형

Compound SORTKEY

  • • 컬럼 순서대로 정렬
  • • 첫 번째 컬럼 필터 시 효과적
  • • 범위 쿼리에 최적
SORTKEY (date, region)

Interleaved SORTKEY

  • • 모든 컬럼 동등하게 정렬
  • • 다양한 필터 조합에 유연
  • • VACUUM 비용 높음
INTERLEAVED SORTKEY (a, b, c)
-- 시계열 데이터: 날짜를 첫 번째 정렬키
CREATE TABLE sales (
  sale_date DATE,
  product_id INT,
  amount DECIMAL(10,2)
)
SORTKEY (sale_date, product_id);

-- Zone Map 활용
-- Redshift는 각 블록의 min/max 값을 저장
-- WHERE sale_date = '2024-01-15' 시 해당 블록만 스캔

┌─────────────────────────────────────────────────────────────────────┐
│  Block 1: sale_date [2024-01-01 ~ 2024-01-10]  → 스킵             │
│  Block 2: sale_date [2024-01-11 ~ 2024-01-20]  → 스캔 ✓           │
│  Block 3: sale_date [2024-01-21 ~ 2024-01-31]  → 스킵             │
└─────────────────────────────────────────────────────────────────────┘

2.3 테이블 설계 Best Practices

권장

  • • JOIN 컬럼을 DISTKEY로
  • • 날짜/시간을 첫 번째 SORTKEY
  • • 작은 테이블은 DISTSTYLE ALL
  • • 압축 인코딩 자동 적용 (ENCODE AUTO)

피해야 할 것

  • • 고유 ID를 DISTKEY로 (데이터 편중)
  • • 너무 많은 SORTKEY 컬럼
  • • INTERLEAVED 남용 (VACUUM 비용)
  • • 불필요한 VARCHAR 크기

3. Redshift Serverless & Spectrum

3.1 Redshift Serverless

Serverless vs Provisioned
특성ServerlessProvisioned
관리완전 자동클러스터 관리 필요
스케일링자동 (RPU 기반)수동/Elastic Resize
비용사용량 기반 (RPU-시간)노드 시간 기반
시작 시간즉시 (웜 풀)수 분
적합한 사용간헐적, 예측 불가지속적, 예측 가능

// Terraform - Redshift Serverless

resource "aws_redshiftserverless_namespace" "analytics" {
  namespace_name      = "analytics"
  db_name            = "analytics_db"
  admin_username     = "admin"
  admin_user_password = var.admin_password
  
  iam_roles = [aws_iam_role.redshift.arn]
}

resource "aws_redshiftserverless_workgroup" "analytics" {
  namespace_name = aws_redshiftserverless_namespace.analytics.namespace_name
  workgroup_name = "analytics-workgroup"
  
  base_capacity = 32  # RPU (8~512)
  
  config_parameter {
    parameter_key   = "max_query_execution_time"
    parameter_value = "3600"  # 1시간
  }
}

3.2 Redshift Spectrum

S3 데이터 직접 쿼리

Redshift Spectrum은 S3에 저장된 데이터를 Redshift로 로드하지 않고 직접 쿼리합니다. Data Lake와 Data Warehouse를 통합하는 Lakehouse 패턴을 구현합니다.

┌─────────────────────────────────────────────────────────────────────┐
│                    Redshift Spectrum Architecture                    │
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │                      Redshift Cluster                            ││
│  │  ┌─────────────┐    ┌─────────────────────────────────────────┐ ││
│  │  │ Local Data  │    │         External Schema                 │ ││
│  │  │ (Redshift)  │    │  CREATE EXTERNAL SCHEMA spectrum_schema │ ││
│  │  │             │    │  FROM DATA CATALOG                      │ ││
│  │  └─────────────┘    └──────────────────┬──────────────────────┘ ││
│  └─────────────────────────────────────────┼────────────────────────┘│
│                                            │                         │
│                                            ▼                         │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │                    Spectrum Layer                                ││
│  │  • 수천 개의 임시 노드로 병렬 처리                               ││
│  │  • Parquet/ORC 컬럼 프루닝                                       ││
│  │  • 파티션 프루닝                                                 ││
│  └──────────────────────────┬──────────────────────────────────────┘│
│                             │                                        │
│                             ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │                         S3 Data Lake                             ││
│  │  s3://data-lake/                                                 ││
│  │  └── historical_orders/year=2023/month=01/                      ││
│  └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘

// Spectrum 설정 및 쿼리

-- External Schema 생성 (Glue Catalog 연결)
CREATE EXTERNAL SCHEMA spectrum_schema
FROM DATA CATALOG
DATABASE 'analytics_db'
IAM_ROLE 'arn:aws:iam::123456789:role/RedshiftSpectrumRole'
REGION 'ap-northeast-2';

-- S3 데이터 직접 쿼리
SELECT 
  DATE_TRUNC('month', order_date) as month,
  SUM(amount) as total_sales
FROM spectrum_schema.historical_orders
WHERE year = '2023'
GROUP BY 1;

-- Redshift 로컬 + S3 조인 (Lakehouse 패턴)
SELECT 
  c.customer_name,
  SUM(o.amount) as total_amount
FROM redshift_schema.customers c
JOIN spectrum_schema.orders o ON c.customer_id = o.customer_id
WHERE o.year = '2024'
GROUP BY 1;

💡 Spectrum 비용 최적화

  • Parquet/ORC 사용: 컬럼 프루닝으로 스캔량 감소
  • 파티셔닝: 필요한 파티션만 스캔
  • 자주 쿼리하는 데이터: Redshift로 로드 고려

4. 정리 및 다음 세션 예고

4.1 핵심 요약

MPP 아키텍처

Leader Node가 쿼리를 분산하고 Compute Node가 병렬 처리. RA3 노드로 컴퓨팅/스토리지 독립 확장.

테이블 설계

DISTKEY로 JOIN 최적화, SORTKEY로 범위 쿼리 최적화. Zone Map을 활용한 블록 스킵으로 I/O 감소.

Serverless vs Provisioned

Serverless는 간헐적 워크로드에 적합, 자동 스케일링. Provisioned는 지속적 워크로드에 비용 효율적.

Spectrum

S3 데이터를 로드 없이 직접 쿼리. Lakehouse 패턴 구현. Parquet + 파티셔닝으로 비용 최적화.

4.2 다음 세션 예고

Session 7: 데이터 쿼리 & 분석

Athena, QuickSight, OpenSearch를 활용한 데이터 분석 방법을 학습합니다.

  • Amazon Athena 심층 분석 및 비용 최적화
  • Amazon QuickSight 대시보드 및 SPICE
  • Amazon OpenSearch 검색 및 로그 분석

5. Redshift 성능 최적화

Redshift 성능 최적화는 쿼리 성능, 데이터 로딩, 워크로드 관리 등 여러 측면에서 접근해야 합니다.

쿼리 최적화 전략
┌─────────────────────────────────────────────────────────────────────────────┐
│                    Query Optimization Strategies                             │
│                                                                              │
│  1. 컬럼 선택 최적화                                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  ❌ SELECT * FROM orders WHERE order_date = '2024-01-15'               ││
│  │  ✅ SELECT order_id, customer_id, amount                               ││
│  │     FROM orders WHERE order_date = '2024-01-15'                        ││
│  │                                                                          ││
│  │  → 컬럼 스토어이므로 필요한 컬럼만 선택                                  ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                                                                              │
│  2. SORTKEY 활용                                                             │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  -- SORTKEY가 order_date인 경우                                        ││
│  │  ✅ WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31'             ││
│  │     → Zone Map으로 블록 스킵                                            ││
│  │                                                                          ││
│  │  ❌ WHERE EXTRACT(month FROM order_date) = 1                           ││
│  │     → 함수 적용 시 Zone Map 무효화                                      ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                                                                              │
│  3. DISTKEY 활용                                                             │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  -- 두 테이블 모두 customer_id가 DISTKEY인 경우                        ││
│  │  SELECT * FROM orders o                                                 ││
│  │  JOIN customers c ON o.customer_id = c.customer_id                     ││
│  │  → 네트워크 전송 없이 로컬 조인                                         ││
│  └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘

5.1 EXPLAIN 분석

실행 계획 분석
-- 실행 계획 확인
EXPLAIN
SELECT c.customer_name, SUM(o.amount) as total_amount
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.order_date >= '2024-01-01'
GROUP BY c.customer_name
ORDER BY total_amount DESC
LIMIT 100;

-- 실행 계획 결과 예시
XN Limit  (cost=1000000000000.00..1000000000000.10 rows=100)
  ->  XN Merge  (cost=1000000000000.00..1000000000000.10 rows=1000)
        Merge Key: sum(o.amount)
        ->  XN Network  (cost=1000000000000.00..1000000000000.10 rows=1000)
              Send to leader
              ->  XN Sort  (cost=1000000000000.00..1000000000000.10 rows=1000)
                    Sort Key: sum(o.amount)
                    ->  XN HashAggregate  (cost=100000.00..100001.00 rows=1000)
                          ->  XN Hash Join DS_DIST_NONE  -- ✅ 로컬 조인
                                Hash Cond: (o.customer_id = c.customer_id)
                                ->  XN Seq Scan on orders o
                                      Filter: (order_date >= '2024-01-01')
                                ->  XN Hash  (cost=1000.00..1000.00 rows=10000)
                                      ->  XN Seq Scan on customers c

좋은 징후

  • • DS_DIST_NONE: 로컬 조인
  • • DS_DIST_ALL_NONE: 브로드캐스트 조인
  • • Zone Map 필터링

경고 징후

  • • DS_DIST_BOTH: 양쪽 재분배
  • • DS_BCAST_INNER: 큰 테이블 브로드캐스트
  • • Nested Loop: 비효율적 조인

5.2 데이터 로딩 최적화

// COPY 명령 최적화

-- 최적화된 COPY 명령
COPY orders
FROM 's3://data-lake/orders/'
IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftCopyRole'
FORMAT AS PARQUET
COMPUPDATE OFF          -- 압축 분석 스킵 (이미 알고 있는 경우)
STATUPDATE OFF          -- 통계 업데이트 스킵 (나중에 ANALYZE)
MAXERROR 100            -- 최대 100개 에러 허용
MANIFEST                -- 매니페스트 파일 사용
;

-- 매니페스트 파일 예시 (manifest.json)
{
  "entries": [
    {"url": "s3://data-lake/orders/part-00000.parquet", "mandatory": true},
    {"url": "s3://data-lake/orders/part-00001.parquet", "mandatory": true},
    {"url": "s3://data-lake/orders/part-00002.parquet", "mandatory": true}
  ]
}

-- 슬라이스 수에 맞춘 파일 분할
-- 노드당 슬라이스 수 × 노드 수 = 총 슬라이스
-- 예: dc2.large 2개 노드 = 4 슬라이스 → 4의 배수 파일

-- 로딩 후 통계 업데이트
ANALYZE orders;

-- 또는 특정 컬럼만
ANALYZE orders (order_date, customer_id);

// VACUUM 및 유지보수

-- 삭제된 행 정리 및 정렬
VACUUM FULL orders;

-- 삭제된 행만 정리 (빠름)
VACUUM DELETE ONLY orders;

-- 정렬만 수행
VACUUM SORT ONLY orders;

-- 자동 VACUUM 설정 확인
SELECT * FROM svv_table_info 
WHERE "table" = 'orders';

-- 테이블 상태 확인
SELECT 
    "table",
    tbl_rows,
    unsorted,           -- 정렬되지 않은 행 비율
    stats_off,          -- 통계 오래된 정도
    pct_used            -- 사용된 공간 비율
FROM svv_table_info
WHERE schema = 'public'
ORDER BY unsorted DESC;

5.3 워크로드 관리 (WLM)

WLM 구성
┌─────────────────────────────────────────────────────────────────────────────┐
│                    Workload Management (WLM)                                 │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  Queue Configuration                                                    ││
│  │                                                                          ││
│  │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         ││
│  │  │  ETL Queue      │  │  BI Queue       │  │  Ad-hoc Queue   │         ││
│  │  │                 │  │                 │  │                 │         ││
│  │  │  Memory: 40%    │  │  Memory: 40%    │  │  Memory: 20%    │         ││
│  │  │  Concurrency: 5 │  │  Concurrency: 10│  │  Concurrency: 5 │         ││
│  │  │  Timeout: 3600s │  │  Timeout: 300s  │  │  Timeout: 60s   │         ││
│  │  │                 │  │                 │  │                 │         ││
│  │  │  User Groups:   │  │  User Groups:   │  │  User Groups:   │         ││
│  │  │  - etl_users    │  │  - bi_users     │  │  - analysts     │         ││
│  │  └─────────────────┘  └─────────────────┘  └─────────────────┘         ││
│  │                                                                          ││
│  │  Query Routing Rules:                                                   ││
│  │  • User group membership                                                ││
│  │  • Query group label                                                    ││
│  │  • Query priority                                                       ││
│  └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘

// WLM 쿼리 그룹 사용

-- 쿼리 그룹 설정
SET query_group TO 'etl';

-- ETL 쿼리 실행
INSERT INTO analytics.daily_summary
SELECT ...
FROM orders
WHERE order_date = CURRENT_DATE - 1;

-- 쿼리 그룹 초기화
RESET query_group;

-- 쿼리 우선순위 설정 (Automatic WLM)
SET query_priority TO 'HIGH';

-- 현재 실행 중인 쿼리 확인
SELECT 
    query,
    pid,
    user_name,
    query_group,
    slot_count,
    DATEDIFF(second, starttime, GETDATE()) as runtime_seconds,
    SUBSTRING(querytxt, 1, 50) as query_text
FROM stv_recents
WHERE status = 'Running'
ORDER BY runtime_seconds DESC;

-- 장시간 실행 쿼리 취소
CANCEL <pid>;

성능 최적화 체크리스트

테이블 설계
  • ☐ 적절한 DISTKEY 선택
  • ☐ SORTKEY 설정 (범위 쿼리 컬럼)
  • ☐ 압축 인코딩 최적화
  • ☐ 적절한 데이터 타입
쿼리 최적화
  • ☐ SELECT * 피하기
  • ☐ SORTKEY 컬럼 필터링
  • ☐ 조인 키 = DISTKEY
  • ☐ EXPLAIN 분석
데이터 로딩
  • ☐ 슬라이스 수 배수 파일
  • ☐ Parquet/ORC 포맷
  • ☐ MANIFEST 사용
  • ☐ ANALYZE 실행
유지보수
  • ☐ 정기적 VACUUM
  • ☐ 통계 업데이트
  • ☐ WLM 큐 모니터링
  • ☐ 디스크 사용량 확인

6. Redshift 데이터 공유 & 보안

6.1 데이터 공유 (Data Sharing)

Cross-Cluster 데이터 공유
┌─────────────────────────────────────────────────────────────────────────────┐
│                    Redshift Data Sharing                                     │
│                                                                              │
│  Producer Cluster (Account A)                                                │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  Database: analytics_db                                                 ││
│  │  ├── Schema: sales                                                      ││
│  │  │   ├── Table: orders                                                  ││
│  │  │   ├── Table: customers                                               ││
│  │  │   └── View: daily_summary                                            ││
│  │  │                                                                       ││
│  │  │  Datashare: sales_share                                              ││
│  │  │  └── Objects: sales.orders, sales.customers, sales.daily_summary    ││
│  │  └───────────────────────────────────────────────────────────────────────││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                              │                                               │
│                              │ Grant to Consumer                            │
│                              ▼                                               │
│  Consumer Cluster (Account B)                                                │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  Database from Datashare: sales_db                                      ││
│  │  ├── Schema: sales                                                      ││
│  │  │   ├── Table: orders (read-only)                                      ││
│  │  │   ├── Table: customers (read-only)                                   ││
│  │  │   └── View: daily_summary (read-only)                                ││
│  │  │                                                                       ││
│  │  │  → 실시간 데이터 접근 (복사 없음)                                     ││
│  │  │  → 스토리지 비용 없음                                                 ││
│  │  └───────────────────────────────────────────────────────────────────────││
│  └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘

// Producer 클러스터에서 Datashare 생성

-- 1. Datashare 생성
CREATE DATASHARE sales_share;

-- 2. 스키마 추가
ALTER DATASHARE sales_share ADD SCHEMA sales;

-- 3. 테이블 추가
ALTER DATASHARE sales_share ADD TABLE sales.orders;
ALTER DATASHARE sales_share ADD TABLE sales.customers;

-- 4. 뷰 추가
ALTER DATASHARE sales_share ADD TABLE sales.daily_summary;

-- 5. 모든 테이블 추가 (스키마 내)
ALTER DATASHARE sales_share ADD ALL TABLES IN SCHEMA sales;

-- 6. Consumer에게 권한 부여
-- 같은 계정 내 다른 클러스터
GRANT USAGE ON DATASHARE sales_share TO NAMESPACE 'consumer-namespace-id';

-- 다른 AWS 계정
GRANT USAGE ON DATASHARE sales_share TO ACCOUNT '123456789012';

-- Datashare 상태 확인
SELECT * FROM svv_datashares;
SELECT * FROM svv_datashare_objects;

// Consumer 클러스터에서 Datashare 사용

-- 1. 사용 가능한 Datashare 확인
SELECT * FROM svv_datashares WHERE share_type = 'INBOUND';

-- 2. Datashare에서 데이터베이스 생성
CREATE DATABASE sales_db FROM DATASHARE sales_share 
OF NAMESPACE 'producer-namespace-id';

-- 또는 다른 계정에서
CREATE DATABASE sales_db FROM DATASHARE sales_share 
OF ACCOUNT '987654321098';

-- 3. 데이터 쿼리 (읽기 전용)
SELECT * FROM sales_db.sales.orders 
WHERE order_date >= '2024-01-01';

-- 4. 로컬 테이블과 조인
SELECT 
    o.order_id,
    o.amount,
    l.region_name
FROM sales_db.sales.orders o
JOIN local_db.public.regions l ON o.region_id = l.region_id;

-- 5. 권한 관리
GRANT USAGE ON DATABASE sales_db TO analyst_role;
GRANT SELECT ON ALL TABLES IN SCHEMA sales_db.sales TO analyst_role;

6.2 보안 설정

행/컬럼 수준 보안

// Row-Level Security (RLS)

-- 1. RLS 정책 생성
CREATE RLS POLICY region_policy
WITH (region VARCHAR(50))
USING (region = current_setting('app.user_region'));

-- 2. 테이블에 정책 적용
ALTER TABLE orders ATTACH RLS POLICY region_policy;

-- 3. RLS 활성화
ALTER TABLE orders ROW LEVEL SECURITY ON;

-- 4. 사용자별 리전 설정
-- 세션 시작 시
SET app.user_region = 'APAC';

-- 쿼리 실행 (자동으로 APAC 데이터만 반환)
SELECT * FROM orders;  -- WHERE region = 'APAC' 자동 적용

-- 5. RLS 정책 확인
SELECT * FROM svv_rls_policy;
SELECT * FROM svv_rls_attached_policy;

// Column-Level Security

-- 1. 역할 생성
CREATE ROLE analyst_role;
CREATE ROLE admin_role;

-- 2. 컬럼별 권한 부여
-- analyst_role: PII 컬럼 제외
GRANT SELECT (order_id, product_id, amount, order_date) 
ON orders TO analyst_role;

-- admin_role: 모든 컬럼
GRANT SELECT ON orders TO admin_role;

-- 3. 동적 데이터 마스킹 (DDM)
CREATE MASKING POLICY email_mask
WITH (email VARCHAR(255))
USING (
    CASE 
        WHEN current_user_has_role('admin_role') THEN email
        ELSE CONCAT(LEFT(email, 2), '***@***.com')
    END
);

-- 4. 마스킹 정책 적용
ALTER TABLE customers 
ATTACH MASKING POLICY email_mask ON email;

-- 5. 결과 확인
-- admin_role: john.doe@example.com
-- analyst_role: jo***@***.com

6.3 감사 로깅

활동 모니터링
-- 사용자 활동 로그 조회
SELECT 
    userid,
    query,
    database,
    querytxt,
    starttime,
    endtime,
    DATEDIFF(second, starttime, endtime) as duration_sec
FROM stl_query
WHERE userid > 1  -- 시스템 사용자 제외
AND starttime >= DATEADD(day, -7, GETDATE())
ORDER BY starttime DESC
LIMIT 100;

-- 연결 로그
SELECT 
    event,
    recordtime,
    username,
    dbname,
    remotehost,
    remoteport
FROM stl_connection_log
WHERE recordtime >= DATEADD(day, -1, GETDATE())
ORDER BY recordtime DESC;

-- 권한 변경 로그
SELECT 
    userid,
    query,
    querytxt,
    starttime
FROM stl_ddltext
WHERE querytxt ILIKE '%GRANT%' OR querytxt ILIKE '%REVOKE%'
ORDER BY starttime DESC;

-- S3로 감사 로그 내보내기 (클러스터 설정)
-- AWS Console에서 Audit Logging 활성화
-- - User activity log
-- - User log  
-- - Connection log

시스템 테이블

  • • STL_QUERY: 쿼리 실행 기록
  • • STL_CONNECTION_LOG: 연결 기록
  • • STL_DDLTEXT: DDL 명령 기록
  • • SVV_TABLE_INFO: 테이블 정보

CloudTrail 통합

  • • API 호출 기록
  • • 클러스터 관리 작업
  • • IAM 인증 이벤트
  • • S3 접근 로그

7. 핵심 요약

Amazon Redshift 핵심 포인트

아키텍처

  • • MPP (Massively Parallel Processing): 여러 노드에서 병렬 처리
  • • 컬럼 스토어: 분석 쿼리에 최적화, 압축 효율
  • • Leader Node: 쿼리 파싱, 실행 계획, 결과 집계
  • • Compute Node: 실제 데이터 저장 및 쿼리 실행
  • • RA3 노드: 컴퓨팅/스토리지 분리, Managed Storage

테이블 설계

  • • DISTKEY: 조인 키 컬럼, 데이터 분산 결정
  • • DISTSTYLE: KEY, ALL, EVEN, AUTO
  • • SORTKEY: 범위 쿼리 컬럼, Zone Map 활용
  • • COMPOUND vs INTERLEAVED SORTKEY
  • • 압축 인코딩: AZ64, LZO, ZSTD 등

Redshift Serverless

  • • RPU (Redshift Processing Unit) 기반 과금
  • • 자동 스케일링, 용량 관리 불필요
  • • Workgroup + Namespace 구조
  • • 가변적 워크로드에 적합

Redshift Spectrum

  • • S3 데이터 직접 쿼리 (External Table)
  • • Glue Data Catalog 통합
  • • 콜드 데이터 분리로 비용 절감
  • • Parquet + 파티셔닝 권장

성능 최적화

  • • EXPLAIN으로 실행 계획 분석
  • • DS_DIST_NONE = 로컬 조인 (최적)
  • • VACUUM: 삭제된 행 정리, 정렬
  • • ANALYZE: 통계 업데이트
  • • WLM: 워크로드별 큐 분리

데이터 공유 & 보안

  • • Data Sharing: Cross-cluster 실시간 공유
  • • RLS (Row-Level Security): 행 수준 접근 제어
  • • DDM (Dynamic Data Masking): 컬럼 마스킹
  • • 감사 로깅: STL 테이블, CloudTrail

🎯 시험 포인트

DISTKEY 선택

조인 키 = DISTKEY → 네트워크 전송 없이 로컬 조인

SORTKEY 선택

WHERE 절 범위 조건 컬럼 → Zone Map 블록 스킵

RA3 vs DC2

RA3 = 대용량, 컴퓨팅/스토리지 분리 | DC2 = 소규모, SSD

Spectrum 비용

스캔 데이터량 기반 → Parquet + 파티셔닝 필수

Serverless vs Provisioned

Serverless = 가변 워크로드 | Provisioned = 예측 가능

Data Sharing

복사 없이 실시간 공유, 읽기 전용, 스토리지 비용 없음

Redshift vs Athena 선택 기준

기준RedshiftAthena
쿼리 패턴복잡한 조인, 반복 쿼리Ad-hoc, 탐색적 분석
데이터 크기TB~PB (자주 접근)GB~TB (간헐적 접근)
동시성높은 동시성 지원제한적 (계정당 한도)
비용 모델노드/RPU 시간스캔 데이터량
관리클러스터 관리 필요서버리스
권장 사용BI 대시보드, 정기 리포트로그 분석, 데이터 탐색

아키텍처 패턴

┌─────────────────────────────────────────────────────────────────────────────┐
│                    Lakehouse Architecture with Redshift                      │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │                         S3 Data Lake                                    ││
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                     ││
│  │  │    Raw      │  │   Curated   │  │  Analytics  │                     ││
│  │  │  (Bronze)   │  │  (Silver)   │  │   (Gold)    │                     ││
│  │  └─────────────┘  └─────────────┘  └─────────────┘                     ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                              │                                               │
│              ┌───────────────┼───────────────┐                              │
│              ▼               ▼               ▼                              │
│  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐               │
│  │     Athena      │ │    Redshift     │ │   Redshift      │               │
│  │   (Ad-hoc)      │ │   (Hot Data)    │ │   Spectrum      │               │
│  │                 │ │                 │ │   (Cold Data)   │               │
│  │  • 탐색적 분석  │ │  • 자주 쿼리    │ │  • S3 직접 쿼리 │               │
│  │  • 로그 분석    │ │  • BI 대시보드  │ │  • 히스토리     │               │
│  └─────────────────┘ └─────────────────┘ └─────────────────┘               │
│                              │                                               │
│                              ▼                                               │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │                       QuickSight                                        ││
│  │                    (Visualization)                                      ││
│  └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘

8. Redshift ML & 고급 분석

Redshift ML을 사용하면 SQL만으로 머신러닝 모델을 생성하고 예측할 수 있습니다. SageMaker Autopilot과 통합되어 자동으로 최적의 모델을 선택합니다.

Redshift ML 아키텍처
┌─────────────────────────────────────────────────────────────────────────────┐
│                    Redshift ML Architecture                                  │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  Redshift Cluster                                                       ││
│  │                                                                          ││
│  │  CREATE MODEL customer_churn_model                                      ││
│  │  FROM training_data                                                     ││
│  │  TARGET churn                                                           ││
│  │  FUNCTION predict_churn                                                 ││
│  │  IAM_ROLE 'arn:aws:iam::xxx:role/RedshiftML'                           ││
│  │  SETTINGS (S3_BUCKET 'ml-bucket')                                       ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                              │                                               │
│                              ▼                                               │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  SageMaker Autopilot                                                    ││
│  │                                                                          ││
│  │  1. 데이터 분석 및 전처리                                                ││
│  │  2. 여러 알고리즘 자동 시도                                              ││
│  │     • XGBoost                                                           ││
│  │     • Linear Learner                                                    ││
│  │     • Deep Learning                                                     ││
│  │  3. 하이퍼파라미터 튜닝                                                  ││
│  │  4. 최적 모델 선택                                                       ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                              │                                               │
│                              ▼                                               │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  Redshift에서 예측                                                      ││
│  │                                                                          ││
│  │  SELECT customer_id, predict_churn(features...)                        ││
│  │  FROM customers                                                         ││
│  │  WHERE predict_churn(features...) > 0.7                                ││
│  └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘

8.1 ML 모델 생성

// 고객 이탈 예측 모델

-- 1. 학습 데이터 준비
CREATE TABLE training_data AS
SELECT 
    customer_id,
    tenure_months,
    monthly_charges,
    total_charges,
    contract_type,
    payment_method,
    num_support_tickets,
    CASE WHEN churned = 'Yes' THEN 1 ELSE 0 END as churn
FROM customer_history
WHERE data_date < '2024-01-01';

-- 2. ML 모델 생성 (자동 알고리즘 선택)
CREATE MODEL customer_churn_model
FROM training_data
TARGET churn
FUNCTION predict_churn
IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftMLRole'
AUTO ON
SETTINGS (
    S3_BUCKET 'redshift-ml-bucket',
    MAX_RUNTIME 3600
);

-- 3. 모델 상태 확인
SHOW MODEL customer_churn_model;

-- 4. 모델 정확도 확인
SELECT 
    accuracy,
    precision,
    recall,
    f1_score
FROM stv_ml_model_info
WHERE model_name = 'customer_churn_model';

// 예측 실행

-- 5. 이탈 가능성 높은 고객 예측
SELECT 
    c.customer_id,
    c.customer_name,
    c.email,
    predict_churn(
        c.tenure_months,
        c.monthly_charges,
        c.total_charges,
        c.contract_type,
        c.payment_method,
        c.num_support_tickets
    ) as churn_probability
FROM customers c
WHERE predict_churn(
    c.tenure_months,
    c.monthly_charges,
    c.total_charges,
    c.contract_type,
    c.payment_method,
    c.num_support_tickets
) > 0.7
ORDER BY churn_probability DESC;

-- 6. 배치 예측 결과 저장
CREATE TABLE churn_predictions AS
SELECT 
    customer_id,
    predict_churn(...) as churn_probability,
    CURRENT_DATE as prediction_date
FROM customers;

-- 7. 모델 재학습 (새 데이터로)
CREATE MODEL customer_churn_model_v2
FROM (
    SELECT * FROM training_data
    UNION ALL
    SELECT * FROM new_training_data
)
TARGET churn
FUNCTION predict_churn_v2
IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftMLRole';

8.2 고급 분석 함수

윈도우 함수 & 분석

// 고급 윈도우 함수

-- 1. 누적 합계 및 이동 평균
SELECT 
    order_date,
    daily_revenue,
    SUM(daily_revenue) OVER (
        ORDER BY order_date 
        ROWS UNBOUNDED PRECEDING
    ) as cumulative_revenue,
    AVG(daily_revenue) OVER (
        ORDER BY order_date 
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) as moving_avg_7d,
    daily_revenue - LAG(daily_revenue, 1) OVER (ORDER BY order_date) as daily_change,
    ROUND(
        (daily_revenue - LAG(daily_revenue, 1) OVER (ORDER BY order_date)) 
        / LAG(daily_revenue, 1) OVER (ORDER BY order_date) * 100, 2
    ) as pct_change
FROM daily_sales;

-- 2. 순위 및 백분위
SELECT 
    product_id,
    product_name,
    total_sales,
    ROW_NUMBER() OVER (ORDER BY total_sales DESC) as rank,
    RANK() OVER (ORDER BY total_sales DESC) as rank_with_ties,
    DENSE_RANK() OVER (ORDER BY total_sales DESC) as dense_rank,
    NTILE(4) OVER (ORDER BY total_sales DESC) as quartile,
    PERCENT_RANK() OVER (ORDER BY total_sales) as percentile
FROM product_sales;

-- 3. 카테고리별 순위
SELECT 
    category,
    product_name,
    total_sales,
    RANK() OVER (PARTITION BY category ORDER BY total_sales DESC) as category_rank
FROM product_sales
QUALIFY category_rank <= 5;  -- 카테고리별 상위 5개

// 코호트 분석

-- 4. 코호트 분석 (고객 유지율)
WITH cohort_data AS (
    SELECT 
        customer_id,
        DATE_TRUNC('month', first_order_date) as cohort_month,
        DATE_TRUNC('month', order_date) as order_month
    FROM orders
),
cohort_size AS (
    SELECT 
        cohort_month,
        COUNT(DISTINCT customer_id) as cohort_customers
    FROM cohort_data
    GROUP BY cohort_month
),
retention AS (
    SELECT 
        cohort_month,
        order_month,
        DATEDIFF(month, cohort_month, order_month) as month_number,
        COUNT(DISTINCT customer_id) as retained_customers
    FROM cohort_data
    GROUP BY cohort_month, order_month
)
SELECT 
    r.cohort_month,
    r.month_number,
    r.retained_customers,
    cs.cohort_customers,
    ROUND(r.retained_customers::FLOAT / cs.cohort_customers * 100, 2) as retention_rate
FROM retention r
JOIN cohort_size cs ON r.cohort_month = cs.cohort_month
ORDER BY r.cohort_month, r.month_number;

-- 5. RFM 분석
WITH rfm AS (
    SELECT 
        customer_id,
        DATEDIFF(day, MAX(order_date), CURRENT_DATE) as recency,
        COUNT(*) as frequency,
        SUM(amount) as monetary
    FROM orders
    WHERE order_date >= DATEADD(year, -1, CURRENT_DATE)
    GROUP BY customer_id
),
rfm_scores AS (
    SELECT 
        customer_id,
        recency,
        frequency,
        monetary,
        NTILE(5) OVER (ORDER BY recency DESC) as r_score,
        NTILE(5) OVER (ORDER BY frequency) as f_score,
        NTILE(5) OVER (ORDER BY monetary) as m_score
    FROM rfm
)
SELECT 
    customer_id,
    r_score,
    f_score,
    m_score,
    CONCAT(r_score, f_score, m_score) as rfm_segment,
    CASE 
        WHEN r_score >= 4 AND f_score >= 4 AND m_score >= 4 THEN 'Champions'
        WHEN r_score >= 3 AND f_score >= 3 THEN 'Loyal Customers'
        WHEN r_score >= 4 AND f_score <= 2 THEN 'New Customers'
        WHEN r_score <= 2 AND f_score >= 3 THEN 'At Risk'
        WHEN r_score <= 2 AND f_score <= 2 THEN 'Lost'
        ELSE 'Others'
    END as customer_segment
FROM rfm_scores;

8.3 Materialized Views

자동 새로고침 뷰
-- Materialized View 생성
CREATE MATERIALIZED VIEW daily_sales_summary
AUTO REFRESH YES
AS
SELECT 
    DATE_TRUNC('day', order_date) as sale_date,
    product_category,
    COUNT(*) as order_count,
    SUM(quantity) as total_quantity,
    SUM(amount) as total_revenue,
    AVG(amount) as avg_order_value,
    COUNT(DISTINCT customer_id) as unique_customers
FROM orders o
JOIN products p ON o.product_id = p.product_id
GROUP BY DATE_TRUNC('day', order_date), product_category;

-- 새로고침 상태 확인
SELECT 
    mv_name,
    state,
    autorefresh,
    last_refresh_time
FROM stv_mv_info
WHERE mv_name = 'daily_sales_summary';

-- 수동 새로고침
REFRESH MATERIALIZED VIEW daily_sales_summary;

-- Materialized View 쿼리 (빠른 응답)
SELECT * FROM daily_sales_summary
WHERE sale_date >= DATEADD(day, -30, CURRENT_DATE)
ORDER BY sale_date DESC;

장점

  • • 복잡한 집계 쿼리 사전 계산
  • • 자동 증분 새로고침
  • • 대시보드 성능 향상

사용 사례

  • • 일별/월별 집계 리포트
  • • BI 대시보드 데이터
  • • 자주 실행되는 복잡한 쿼리

9. Redshift 클러스터 관리

9.1 노드 타입 선택

노드 타입 비교
┌─────────────────────────────────────────────────────────────────────────────┐
│                    Redshift Node Types                                       │
│                                                                              │
│  RA3 Nodes (권장)                                                            │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  ra3.xlplus    │  4 vCPU  │  32 GB  │  32 TB Managed Storage           ││
│  │  ra3.4xlarge   │  12 vCPU │  96 GB  │  128 TB Managed Storage          ││
│  │  ra3.16xlarge  │  48 vCPU │  384 GB │  128 TB Managed Storage          ││
│  │                                                                          ││
│  │  특징:                                                                   ││
│  │  • 컴퓨팅/스토리지 독립 확장                                             ││
│  │  • Managed Storage (S3 기반)                                            ││
│  │  • 자동 데이터 티어링                                                    ││
│  │  • Cross-AZ 데이터 공유                                                  ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                                                                              │
│  DC2 Nodes (SSD)                                                             │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  dc2.large     │  2 vCPU  │  15 GB  │  160 GB SSD                      ││
│  │  dc2.8xlarge   │  32 vCPU │  244 GB │  2.56 TB SSD                     ││
│  │                                                                          ││
│  │  특징:                                                                   ││
│  │  • 로컬 SSD 스토리지                                                     ││
│  │  • 소규모 데이터셋에 적합                                                ││
│  │  • 낮은 비용 (소규모)                                                    ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│                                                                              │
│  선택 가이드:                                                                │
│  • 데이터 > 1TB: RA3 권장                                                   │
│  • 데이터 < 1TB, 예산 제한: DC2                                             │
│  • 스토리지 독립 확장 필요: RA3                                             │
│  • 데이터 공유 필요: RA3 필수                                               │
└─────────────────────────────────────────────────────────────────────────────┘
노드 타입vCPU메모리스토리지시간당 비용
ra3.xlplus432 GB32 TB$1.086
ra3.4xlarge1296 GB128 TB$3.26
ra3.16xlarge48384 GB128 TB$13.04
dc2.large215 GB160 GB$0.25
dc2.8xlarge32244 GB2.56 TB$4.80

9.2 클러스터 크기 조정

Elastic Resize & Concurrency Scaling

// Terraform - 클러스터 구성

resource "aws_redshift_cluster" "main" {
  cluster_identifier = "analytics-cluster"
  database_name      = "analytics"
  master_username    = "admin"
  master_password    = var.master_password
  
  node_type         = "ra3.4xlarge"
  number_of_nodes   = 3
  
  # Elastic Resize 활성화
  elastic_ip = null
  
  # 암호화
  encrypted  = true
  kms_key_id = aws_kms_key.redshift.arn
  
  # 네트워크
  cluster_subnet_group_name    = aws_redshift_subnet_group.main.name
  vpc_security_group_ids       = [aws_security_group.redshift.id]
  publicly_accessible          = false
  
  # 유지보수
  preferred_maintenance_window = "sun:05:00-sun:06:00"
  automated_snapshot_retention_period = 7
  
  # 파라미터 그룹
  cluster_parameter_group_name = aws_redshift_parameter_group.main.name
  
  # IAM 역할
  iam_roles = [
    aws_iam_role.redshift_spectrum.arn,
    aws_iam_role.redshift_ml.arn
  ]
  
  # 로깅
  logging {
    enable        = true
    bucket_name   = aws_s3_bucket.redshift_logs.id
    s3_key_prefix = "redshift-logs/"
  }

  tags = {
    Environment = "production"
  }
}

# 파라미터 그룹
resource "aws_redshift_parameter_group" "main" {
  name   = "analytics-params"
  family = "redshift-1.0"

  parameter {
    name  = "enable_user_activity_logging"
    value = "true"
  }

  parameter {
    name  = "require_ssl"
    value = "true"
  }

  parameter {
    name  = "max_concurrency_scaling_clusters"
    value = "5"
  }

  parameter {
    name  = "wlm_json_configuration"
    value = jsonencode([
      {
        name                  = "etl"
        memory_percent_to_use = 40
        concurrency           = 5
        user_group            = ["etl_users"]
      },
      {
        name                  = "bi"
        memory_percent_to_use = 40
        concurrency           = 15
        user_group            = ["bi_users"]
      },
      {
        name                  = "default"
        memory_percent_to_use = 20
        concurrency           = 5
      }
    ])
  }
}

// 클러스터 관리 명령

-- Elastic Resize (노드 수 변경)
-- AWS CLI 또는 콘솔에서 실행
-- 몇 분 내 완료, 다운타임 최소화

-- Concurrency Scaling 상태 확인
SELECT 
    service_class,
    num_queued_queries,
    num_executing_queries,
    query_working_mem
FROM stv_wlm_service_class_state;

-- 동시성 스케일링 사용량 확인
SELECT 
    DATE_TRUNC('hour', start_time) as hour,
    SUM(total_exec_time) / 1000000.0 as total_seconds,
    COUNT(*) as query_count
FROM svl_query_metrics_summary
WHERE is_concurrency_scaling = 't'
GROUP BY DATE_TRUNC('hour', start_time)
ORDER BY hour DESC;

-- 클러스터 일시 중지/재개 (비용 절감)
-- AWS CLI
-- aws redshift pause-cluster --cluster-identifier analytics-cluster
-- aws redshift resume-cluster --cluster-identifier analytics-cluster

-- 스냅샷 생성
CREATE SNAPSHOT analytics_backup_20240115
FROM analytics_cluster;

-- 스냅샷에서 복원
RESTORE FROM SNAPSHOT analytics_backup_20240115
TO analytics_cluster_restored;

9.3 네트워크 구성

VPC & 보안 그룹
┌─────────────────────────────────────────────────────────────────────────────┐
│                    Redshift Network Architecture                             │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │  VPC (10.0.0.0/16)                                                      ││
│  │                                                                          ││
│  │  ┌─────────────────────────────────────────────────────────────────┐    ││
│  │  │  Private Subnet (10.0.1.0/24)                                   │    ││
│  │  │                                                                 │    ││
│  │  │  ┌─────────────────────────────────────────────────────────┐   │    ││
│  │  │  │  Redshift Cluster                                       │   │    ││
│  │  │  │  • Leader Node                                          │   │    ││
│  │  │  │  • Compute Nodes (3x ra3.4xlarge)                       │   │    ││
│  │  │  │  • Port: 5439                                           │   │    ││
│  │  │  └─────────────────────────────────────────────────────────┘   │    ││
│  │  │                                                                 │    ││
│  │  │  Security Group:                                                │    ││
│  │  │  • Inbound: 5439 from Application SG                           │    ││
│  │  │  • Inbound: 5439 from BI Tools SG                              │    ││
│  │  │  • Outbound: 443 to S3 (Spectrum)                              │    ││
│  │  └─────────────────────────────────────────────────────────────────┘    ││
│  │                                                                          ││
│  │  ┌─────────────────────────────────────────────────────────────────┐    ││
│  │  │  VPC Endpoints                                                  │    ││
│  │  │  • S3 Gateway Endpoint (Spectrum 쿼리)                         │    ││
│  │  │  • Glue Interface Endpoint (Data Catalog)                      │    ││
│  │  │  • SageMaker Interface Endpoint (Redshift ML)                  │    ││
│  │  └─────────────────────────────────────────────────────────────────┘    ││
│  └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘

// Terraform - 네트워크 구성

# Redshift 서브넷 그룹
resource "aws_redshift_subnet_group" "main" {
  name       = "redshift-subnet-group"
  subnet_ids = var.private_subnet_ids

  tags = {
    Name = "Redshift Subnet Group"
  }
}

# 보안 그룹
resource "aws_security_group" "redshift" {
  name        = "redshift-sg"
  description = "Security group for Redshift cluster"
  vpc_id      = var.vpc_id

  # 애플리케이션에서 접근
  ingress {
    from_port       = 5439
    to_port         = 5439
    protocol        = "tcp"
    security_groups = [var.app_security_group_id]
  }

  # BI 도구에서 접근
  ingress {
    from_port       = 5439
    to_port         = 5439
    protocol        = "tcp"
    security_groups = [var.bi_security_group_id]
  }

  # S3 (Spectrum) 접근
  egress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    prefix_list_ids = [aws_vpc_endpoint.s3.prefix_list_id]
  }

  tags = {
    Name = "Redshift Security Group"
  }
}

# S3 Gateway Endpoint
resource "aws_vpc_endpoint" "s3" {
  vpc_id       = var.vpc_id
  service_name = "com.amazonaws.${var.region}.s3"
  
  route_table_ids = var.private_route_table_ids
}

클러스터 관리 체크리스트

성능
  • ☐ 적절한 노드 타입 선택
  • ☐ WLM 큐 구성
  • ☐ Concurrency Scaling 활성화
  • ☐ 정기적 VACUUM/ANALYZE
보안
  • ☐ KMS 암호화 활성화
  • ☐ SSL 연결 강제
  • ☐ VPC 내 배치
  • ☐ 감사 로깅 활성화