Redshift 설정

Redshift 설정

dbt-redshift 어댑터의 설정을 정리한 페이지예요. incremental materialization 전략, distkey·sortkey 성능 최적화, 세션 구성(query_group), 데이터셰어링(datasharing), late binding view, materialized view 설정을 소개해요.

출처: dbt 공식 문서

본문

Incremental materialization 전략

dbt-redshift에서 다음 incremental materialization 전략을 지원해요.

  • append (unique_key가 정의되지 않았을 때 기본값)
  • merge
  • delete+insert (unique_key가 정의됐을 때 기본값)
  • microbatch

이 전략들은 모두 dbt-postgres에서 상속받은 것이에요.

성능 최적화

sortkey와 distkey 사용하기

Amazon Redshift의 테이블에는 쿼리 성능을 개선하는 두 가지 강력한 최적화(distkey와 sortkey)가 있어요. 이 값들을 모델 수준 설정으로 제공하면 생성된 CREATE TABLE DDL에 해당 설정이 적용돼요. 이 설정들은 viewephemeral로 설정된 모델에는 효과가 없어요.

  • distall, even, auto, 또는 키 이름으로 설정할 수 있어요.
  • sort는 정렬 키 목록을 받아요. 예: ['reporting_day', 'category']. dbt는 필드가 제공된 순서와 같은 순서로 정렬 키를 만들어요.
  • sort_typeinterleaved 또는 compound로 설정할 수 있어요. 지정하지 않으면 sort_type은 기본값 compound예요.

정렬 키를 다룰 때는 정렬 키의 효과와 카디널리티에 대한 Redshift 모범 사례를 따르는 걸 적극 권장해요.

Sort와 dist 키는 모델 .sql 파일의 {{ config(...) }} 블록에 추가해야 해요. 예를 들어:

my_model.sql

-- Example with one sort key
{{ config(materialized='table', sort='reporting_day', dist='unique_id') }}

select ...

-- Example with multiple sort keys
{{ config(materialized='table', sort=['category', 'region', 'reporting_day'], dist='received_at') }}

select ...

-- Example with interleaved sort keys
{{ config(materialized='table',
          sort_type='interleaved'
          sort=['category', 'region', 'reporting_day'],
          dist='unique_id')
}}

select ...

distkey와 sortkey에 대한 더 자세한 정보는 Amazon 문서를 참고해요.

(dbt v1.12 이상에 적용돼요.)

세션 구성

Redshift 어댑터는 query_group 세션 파라미터를 지원해, dbt 실행이 Redshift Workload Manager(WLM)와 쿼리 로깅(예: STL_QUERY, SVL_QLOG)용 쿼리를 태그할 수 있게 해요. query_group을 프로필 레벨(연결 기본값)로 설정하고 모델 레벨에서 덮어쓸 수 있어요.

  • 프로필 레벨 설정

    profiles.yml에서 query_group을 설정하면 그 프로필로 실행되는 모든 쿼리에 기본값을 적용해요. dbt는 연결을 열 때 query_group을 설정해요.

    profiles.yml

    outputs:
      dev:
        type: redshift
        host: CLUSTER_ENDPOINT
        user: REDSHIFT_USER
        password: REDSHIFT_PASSWORD
        dbname: REDSHIFT_DBNAME
        port: 5439
        schema: analytics
        threads: 4
        query_group: QUERY_GROUP_NAME
    
    -- models/a_default_group.sql
    -- Runs under query_group = 'QUERY_GROUP_NAME' (from the profile)
    select 1 as id
    
  • 모델 레벨 설정

    모델의 config() 블록에 query_group을 설정하면 해당 모델 실행 동안 기본값을 임시로 덮어써요. dbt는 모델 실행 중에는 모델 레벨 값을 적용하고, 모델 materialization 후에는 기본값을 복원해요.

    -- models/b_override_group.sql
    -- dbt temporarily sets query_group = 'dbt_finance' for this model, then restores the default value
    {{ config(query_group='dbt_finance') }}
    
    select 1 as id
    

데이터셰어링 (Datasharing) Beta

이전에는 Redshift 어댑터가 관계·스키마·컬럼을 나열하는 메타데이터 작업에 PostgreSQL 호환 카탈로그 테이블(예: pg_*, information_schema)을 사용했어요. 이 테이블들은 현재 연결된 데이터베이스 안의 객체만 표시하므로, Redshift Datasharing에 필요한 크로스 데이터베이스 작업을 못 하게 막았어요.

dbt-redshift v1.11.0rc1부터 profiles.yml에서 datasharing: true를 설정해 크로스 데이터베이스·크로스 클러스터 접근을 활성화할 수 있어요. 활성화하면 dbt-redshift가 메타데이터 쿼리를 Redshift 네이티브 SHOW 시스템 명령으로 전환해요. 그러면 {{ config(database='other_db') }}를 써서 프로필에 지정된 것과 다른 데이터베이스나 클러스터에 모델을 materialize할 수 있어요.

설정 예시:

profiles.yml

company-name:
  target: dev
  outputs:
    dev:
      type: redshift
      host: hostname.region.redshift.amazonaws.com
      ...
      datasharing: true  # default: false

활성화한 뒤에는 모델 설정에 database를 설정해 다른 데이터베이스로 모델을 materialize할 수 있어요. 예를 들어:

{{ config(database='other_db') }}

select * from {{ ref('my_model') }}

datasharing: true일 때 SHOW 명령으로 전환되는 매크로는 다음과 같아요.

매크로 datasharing 없음 datasharing 있음
list_relations_without_caching information_schema.tables SHOW TABLES FROM SCHEMA
list_schemas, check_schema_exists pg_namespace SHOW SCHEMAS FROM DATABASE
get_columns_in_relation information_schema.columns SHOW COLUMNS FROM TABLE
카탈로그 쿼리 pg_class, pg_tables, pg_views SHOW TABLES FROM SCHEMA + SVV_REDSHIFT_COLUMNS
get_relation_last_modified information_schema.tables SHOW TABLES FROM SCHEMA
Grants pg_user, has_table_privilege() SHOW GRANTS ON TABLE

ra3_node: true도 이 동작을 활성화하며 하위 호환성을 위해 지원돼요. 새 프로젝트에는 대신 datasharing: true를 사용해요.

참고

datasharing을 활성화한 상태에서 pg_* 쿼리가 실행되는 걸 봐도 반드시 버그는 아니에요. 위에 나열한 매크로만 마이그레이션되고, 일부 매크로는 설계상 pg_*에 남아요(예: 의존성 추적용 get_relations, 함수 발견용 list_function_relations_without_caching). 프로젝트의 커스텀 매크로 오버라이드는 영향받지 않아요. pg_* 쿼리가 예상된 것인지 확인하려면 어떤 매크로가 오버라이드되고 어떤 메타데이터 작업이 실행 중인지 확인해요.

datasharing을 사용할 때 다음 제한 사항이 적용돼요.

  • 다른 데이터베이스에서 뷰(materialized view 포함)를 만드는 것은 지원되지 않아요.
  • 객체에 대한 크로스 데이터베이스 grants는 지원되지 않아요.
  • 소스 신선도 확인은 최대 5분까지 지연될 수 있어요.
  • 메타데이터 쿼리는 10,000행으로 제한돼요. 데이터베이스에 스키마가 10,000개를 넘거나 스키마에 테이블이 10,000개를 넘으면 dbt 실행에서 예상치 못한 상황이 생길 수 있어요.
  • 크로스 데이터베이스 쓰기에는 SNAPSHOT 트랜잭션 격리 수준이 필요해요.
  • 다른 데이터베이스의 테이블을 참조하는 뷰는 late-binding view로 정의해요.

설정 방법은 Redshift 셋업을 참고해요.

Late binding views

Redshift는 의존성에 묶이지 않은 뷰, 즉 late binding views를 지원해요. 이 DDL 옵션은 뷰를 데이터를 선택하는 대상에서 "분리(unbind)"해요. 실제로는 업스트림 뷰나 테이블이 cascade 한정자와 함께 드롭돼도 late-binding 뷰는 함께 드롭되지 않는다는 뜻이에요.

프로덕션 dbt 배포에서 late-binding view를 쓰면 웨어하우스의 데이터 가용성이 크게 향상될 수 있어요. 특히 late-binding view로 materialize되고 최종 사용자가 쿼리하는 모델은 업스트림 모델이 업데이트될 때 드롭되지 않으니까요. 또한 late binding view는 Redshift Spectrum을 통한 외부 테이블과 함께 쓸 수 있어요.

dbt 모델을 late binding view로 materialize하려면 bind: false 설정 옵션을 사용해요.

my_view.sql

{{ config(materialized='view', bind=False) }}

select *
from source.data

모든 뷰를 late-binding으로 만들려면 dbt_project.yml 파일을 이렇게 설정해요.

dbt_project.yml

models:
  +bind: false # Materialize all views as late-binding
  project_name:
    ....

Materialized views

Redshift 어댑터는 다음 설정 파라미터와 함께 materialized views를 지원해요.

파라미터 타입 필수 기본값 변경 모니터링 지원
on_configuration_change <string> 아니요 apply n/a
dist <string> 아니요 even drop/create
sort [<string>] 아니요 none drop/create
sort_type <string> 아니요 sort 없으면 auto
sort 있으면 compound
drop/create
auto_refresh <boolean> 아니요 false alter
backup <string> 아니요 true n/a

프로젝트 YAML 파일

dbt_project.yml

models:
  <resource-path>:
    +materialized: materialized_view
    +on_configuration_change: apply | continue | fail
    +dist: all | auto | even | <field-name>
    +sort: <field-name> | [<field-name>]
    +sort_type: auto | compound | interleaved
    +auto_refresh: true | false
    +backup: true | false

프로퍼티 YAML 파일

models/properties.yml


models:
  - name: [<model-name>]
    config:
      materialized: materialized_view
      on_configuration_change: apply | continue | fail
      dist: all | auto | even | <field-name>
      sort: <field-name> | [<field-name>]
      sort_type: auto | compound | interleaved
      auto_refresh: true | false
      backup: true | false

SQL 파일 설정

models/<model_name>.sql

{{ config(
    materialized="materialized_view",
    on_configuration_change="apply" | "continue" | "fail",
    dist="all" | "auto" | "even" | "<field-name>",
    sort=["<field-name>"],
    sort_type="auto" | "compound" | "interleaved",
    auto_refresh=true | false,
    backup=true | false,
) }}

이 파라미터들 중 상당수는 테이블의 것과 대응하며 위에 링크돼 있어요. materialized view에 고유한 파라미터는 auto-refreshbackup 기능인데, 아래에서 다룰게요.

이 파라미터에 대한 자세한 내용은 Redshift의 문서를 참고해요.

Auto-refresh (자동 새로고침)

파라미터 타입 필수 기본값 변경 모니터링 지원
auto_refresh <boolean> 아니요 false alter

Redshift는 materialized view에 자동 새로고침 설정을 지원해요. 기본적으로 materialized view는 자동으로 새로고침되지 않아요. dbt는 이 파라미터의 변경을 모니터링하고 ALTER 문으로 적용해요.

파라미터에 대한 더 자세한 정보는 Redshift 문서에서 확인해요.

Backup (백업)

파라미터 타입 필수 기본값 변경 모니터링 지원
backup <boolean> 아니요 true n/a

Redshift는 객체 레벨에서 클러스터의 backup 설정을 지원해요. 이 파라미터는 materialized view가 클러스터 스냅샷의 일부로 백업되어야 하는지 식별해요. 기본적으로 materialized view는 클러스터 스냅샷 중에 백업돼요. dbt는 이 파라미터가 Redshift 안에서 쿼리할 수 없어서 모니터링하지 못해요. 값이 바뀌면 materialized view는 설정하기 위해 --full-refresh를 거쳐야 해요.

이 파라미터에 대한 더 자세한 정보는 Redshift 문서에서 확인해요.

제한 사항

대부분의 데이터 플랫폼처럼 materialized view에도 제한 사항이 있어요. 주목할 만한 것 몇 가지:

  • materialized view는 뷰, 임시 테이블, 사용자 정의 함수, late-binding 테이블을 참조할 수 없어요.
  • materialized view가 변경 가능한 함수, 외부 스키마, 또는 다른 materialized view를 참조하면 자동 새로고침을 쓸 수 없어요.

materialized view 제한 사항에 대한 더 자세한 정보는 Redshift 문서에서 확인해요.

유닛 테스트 제한 사항

  • Redshift는 공통 테이블 표현식(CTE) 안의 SQL에 LISTAGG, MEDIAN, PERCENTILE_CONT 같은 함수가 있으면 유닛 테스트를 지원하지 않아요. 이 함수들은 사용자가 만든 테이블에 대해 실행해야 해요. dbt는 주어진 행들을 CTE의 일부로 결합하는데, Redshift는 이를 지원하지 않아요.

    미래에 이 패턴을 지원하려면 dbt는 입력 픽스처를 CTE로 보간하는 대신 테이블로 "materialize"해야 해요. 이 기능에 관심이 있다면 GitHub 이슈에서 참여해 주세요: dbt-labs/dbt#8499

  • Redshift는 모델과 다른 데이터베이스의 소스에 의존하는 유닛 테스트를 지원하지 않아요. 자세한 내용은 GitHub 이슈를 참고해요: https://github.com/dbt-labs/dbt-redshift/issues/995

더 알아보기 (Learn more)