Vertica configurations

Vertica configurations

dbt-vertica 어댑터에서 incremental 모델과 테이블 최적화를 구성하는 방법을 다루는 페이지예요. on_schema_change, incremental_strategy, 그리고 CREATE TABLE의 ORDER BY/SEGMENTED BY/PARTITION BY/KSAFE 절을 설정할 수 있어요.

출처: 문서

본문

Incremental Models 구성

on_schema_change config 파라미터 사용

on_schema_change 파라미터는 ignore, fail, append_new_columns 값을 쓸 수 있어요. sync_all_columns 값은 현재 지원되지 않아요.

ignore (기본값) 파라미터 구성

vertica_incremental.sql

{{config(materialized = 'incremental',on_schema_change='ignore')}}

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

vertica_incremental.sql (컴파일 결과)

insert into "VMart"."public"."merge" ("id", "name", "some_date")
    (
        select "id", "name", "some_date"
        from "merge__dbt_tmp"
    )

fail 파라미터 구성

vertica_incremental.sql

{{config(materialized = 'incremental',on_schema_change='fail')}}

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

vertica_incremental.sql (컴파일 결과)

The source and target schemas on this incremental model are out of sync!
              They can be reconciled in several ways:
                - set the `on_schema_change` config to either append_new_columns or sync_all_columns, depending on your situation.
                - Re-run the incremental model with `full_refresh: True` to update the target schema.
                - update the schema manually and re-run the process.

              Additional troubleshooting context:
                 Source columns not in target: {{ schema_changes_dict['source_not_in_target'] }}
                 Target columns not in source: {{ schema_changes_dict['target_not_in_source'] }}
                 New column types: {{ schema_changes_dict['new_target_types'] }}

append_new_columns 파라미터 구성

vertica_incremental.sql

{{ config( materialized='incremental', on_schema_change='append_new_columns') }}

    select * from  public.seed_added

vertica_incremental.sql (컴파일 결과)

insert into "VMart"."public"."over" ("id", "name", "some_date", "w", "w1", "t1", "t2", "t3")
          (
                select "id", "name", "some_date", "w", "w1", "t1", "t2", "t3"
                from "over__dbt_tmp"
          )

incremental_strategy config 파라미터 사용

append 전략 (기본값):

기존 데이터를 갱신하거나 덮어쓰지 않고 새 레코드만 삽입해요. append는 is_incremental() 조건 블록에 지정된 조건을 기반으로 새 레코드만 추가해요.

vertica_incremental.sql

{{ config(  materialized='incremental',     incremental_strategy='append'  ) }}

    select * from  public.product_dimension

    {% if is_incremental() %}

        where product_key > (select max(product_key) from {{this }})

    {% endif %}

vertica_incremental.sql (컴파일 결과)

insert into "VMart"."public"."samp" (

        "product_key", "product_version", "product_description", "sku_number", "category_description",
        "department_description", "package_type_description", "package_size", "fat_content", "diet_type",
        "weight", "weight_units_of_measure", "shelf_width", "shelf_height", "shelf_depth", "product_price",
        "product_cost", "lowest_competitor_price", "highest_competitor_price", "average_competitor_price", "discontinued_flag")
    (
          select "product_key", "product_version", "product_description", "sku_number", "category_description", "department_description", "package_type_description", "package_size", "fat_content", "diet_type", "weight", "weight_units_of_measure", "shelf_width", "shelf_height", "shelf_depth", "product_price", "product_cost", "lowest_competitor_price", "highest_competitor_price", "average_competitor_price", "discontinued_flag"

          from "samp__dbt_tmp"
    )

merge 전략:

unique_key를 기준으로 레코드를 매칭하고, 기존 레코드는 갱신하고 새 것도 삽입해요. (unique_key를 지정하지 않으면 append처럼 모든 새 데이터가 삽입돼요.) merge 전략을 쓰려면 unique_key config 파라미터가 필요한데, 이 파라미터는 단일 테이블 컬럼 값을 받아요.

vertica_incremental.sql

{{ config( materialized = 'incremental', incremental_strategy = 'merge',  unique_key='promotion_key'   )  }}

          select * FROM  public.promotion_dimension

vertica_incremental.sql (컴파일 결과)

merge into "VMart"."public"."samp" as DBT_INTERNAL_DEST using "samp__dbt_tmp" as DBT_INTERNAL_SOURCE
          on DBT_INTERNAL_DEST."promotion_key" = DBT_INTERNAL_SOURCE."promotion_key"

        when matched then update set
        "promotion_key" = DBT_INTERNAL_SOURCE."promotion_key", "price_reduction_type" = DBT_INTERNAL_SOURCE."price_reduction_type", "promotion_media_type" = DBT_INTERNAL_SOURCE."promotion_media_type", "display_type" = DBT_INTERNAL_SOURCE."display_type", "coupon_type" = DBT_INTERNAL_SOURCE."coupon_type", "ad_media_name" = DBT_INTERNAL_SOURCE."ad_media_name", "display_provider" = DBT_INTERNAL_SOURCE."display_provider", "promotion_cost" = DBT_INTERNAL_SOURCE."promotion_cost", "promotion_begin_date" = DBT_INTERNAL_SOURCE."promotion_begin_date", "promotion_end_date" = DBT_INTERNAL_SOURCE."promotion_end_date"

        when not matched then insert
          ("promotion_key", "price_reduction_type", "promotion_media_type", "display_type", "coupon_type",
           "ad_media_name", "display_provider", "promotion_cost", "promotion_begin_date", "promotion_end_date")
        values
        (
          DBT_INTERNAL_SOURCE."promotion_key", DBT_INTERNAL_SOURCE."price_reduction_type", DBT_INTERNAL_SOURCE."promotion_media_type", DBT_INTERNAL_SOURCE."display_type", DBT_INTERNAL_SOURCE."coupon_type", DBT_INTERNAL_SOURCE."ad_media_name", DBT_INTERNAL_SOURCE."display_provider", DBT_INTERNAL_SOURCE."promotion_cost", DBT_INTERNAL_SOURCE."promotion_begin_date", DBT_INTERNAL_SOURCE."promotion_end_date"
        )
merge_update_columns config 파라미터 사용

merge_update_columns config 파라미터는 지정한 컬럼만 갱신하도록 전달되며, 테이블 컬럼 목록을 받아요.

vertica_incremental.sql

{{ config( materialized = 'incremental', incremental_strategy='merge', unique_key = 'id', merge_update_columns = ["names", "salary"] )}}

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

vertica_incremental.sql (컴파일 결과)

merge into "VMart"."public"."test_merge" as DBT_INTERNAL_DEST using "test_merge__dbt_tmp" as DBT_INTERNAL_SOURCE on  DBT_INTERNAL_DEST."id" = DBT_INTERNAL_SOURCE."id"

        when matched then update set
          "names" = DBT_INTERNAL_SOURCE."names", "salary" = DBT_INTERNAL_SOURCE."salary"

        when not matched then insert
        ("id", "names", "salary")
        values
        (
          DBT_INTERNAL_SOURCE."id", DBT_INTERNAL_SOURCE."names", DBT_INTERNAL_SOURCE."salary"
        )

delete+insert 전략:

delete+insert incremental 전략으로 dbt에 두 단계 incremental 접근을 사용하라고 지시할 수 있어요. 먼저 설정된 is_incremental() 블록을 통해 감지된 레코드를 삭제하고, 다시 삽입해요. unique_keydelete+insert 전략에 필수 파라미터로, 중복 데이터가 있을 때 레코드 갱신 방식을 지정해요. 이 파라미터는 단일 테이블 컬럼 값을 받아요.

vertica_incremental.sql

{{ config( materialized = 'incremental', incremental_strategy = 'delete+insert',  unique_key='date_key'   )  }}

          select * FROM  public.date_dimension

vertica_incremental.sql (컴파일 결과)

delete from "VMart"."public"."samp"
            where (
                date_key) in (
                select (date_key)
                from "samp__dbt_tmp"
            );

        insert into "VMart"."public"."samp" (
             "date_key", "date", "full_date_description", "day_of_week", "day_number_in_calendar_month", "day_number_in_calendar_year", "day_number_in_fiscal_month", "day_number_in_fiscal_year", "last_day_in_week_indicator", "last_day_in_month_indicator", "calendar_week_number_in_year", "calendar_month_name", "calendar_month_number_in_year", "calendar_year_month", "calendar_quarter", "calendar_year_quarter", "calendar_half_year", "calendar_year", "holiday_indicator", "weekday_indicator", "selling_season")
        (
            select "date_key", "date", "full_date_description", "day_of_week", "day_number_in_calendar_month", "day_number_in_calendar_year", "day_number_in_fiscal_month", "day_number_in_fiscal_year", "last_day_in_week_indicator", "last_day_in_month_indicator", "calendar_week_number_in_year", "calendar_month_name", "calendar_month_number_in_year", "calendar_year_month", "calendar_quarter", "calendar_year_quarter", "calendar_half_year", "calendar_year", "holiday_indicator", "weekday_indicator", "selling_season"
            from "samp__dbt_tmp"
        );

insert_overwrite 전략:

insert_overwrite 전략은 레코드를 삭제할 때 전체 테이블 스캔을 사용하지 않아요. 레코드를 삭제하는 대신 전체 파티션을 드롭해요. 이 전략은 partition_by_stringpartitions 파라미터를 받을 수 있어요. 테이블 일부를 덮어쓰고 싶을 때 이 파라미터들을 제공해요.

partition_by_string은 테이블 파티셔닝이 일어나는 기준이 되는 표현식을 받아요. 이것은 Vertica의 PARTITION BY 절이에요.

partitions는 파티션 컬럼의 값 목록을 받아요.

partitions config 파라미터는 신중히 사용해야 해요. 두 가지 상황을 고려하세요.

  • partitions 파라미터의 파티션이 where 절보다 적으면: 대상 테이블에 중복이 생겨요.
  • partitions 파라미터의 파티션이 where 절보다 많으면: 대상 테이블에서 행이 누락돼요. 대상이 소스보다 행이 적어져요.

PARTITION BY 절에 대해 더 알아보려면 여기를 확인하세요.

참고: partitions 파라미터는 선택 사항이에요. partitions 파라미터를 제공하지 않으면 where 절의 파티션이 대상에서 드롭되고 소스에서 다시 삽입돼요. where 절을 쓰면 partitions 파라미터가 필요 없을 수 있어요. where 절 조건도 선택 사항이지만, 제공하지 않으면 소스의 모든 데이터가 대상에 삽입돼요. where 절 조건과 partitions 파라미터가 모두 없으면 테이블의 모든 파티션을 드롭하고 전부 다시 삽입해요. partitions 파라미터는 제공했는데 where 절이 없으면, partitions 파라미터의 파티션이 드롭되지만 소스 테이블의 모든 데이터(where 절 없음)가 대상에 삽입되어 대상 테이블에 중복이 생겨요. partition_by_string config 파라미터도 선택 사항이에요. partition_by_string 파라미터를 제공하지 않으면 delete+insert처럼 동작해요. 대상의 모든 레코드를 삭제한 뒤 소스의 모든 레코드를 삽입해요. 파티션을 사용하거나 드롭하지 않아요. partition_by_stringpartitions 파라미터가 모두 없으면 insert_overwrite 전략은 대상 테이블을 truncate하고 소스 테이블 데이터를 대상에 삽입해요. partitions 파라미터를 쓰려면 partition_by_string 파라미터를 전달해 테이블을 파티셔닝해야 해요.

vertica_incremental.sql

{{config(materialized = 'incremental',incremental_strategy = 'insert_overwrite',partition_by_string='YEAR(cc_open_date)',partitions=['2023'])}}

        select * from online_sales.call_center_dimension

vertica_incremental.sql (컴파일 결과)

select PARTITION_TABLE('online_sales.update_call_center_dimension');

        SELECT DROP_PARTITIONS('online_sales.update_call_center_dimension', '2023', '2023');

        SELECT PURGE_PARTITION('online_sales.update_call_center_dimension', '2023');

        insert into "VMart"."online_sales"."update_call_center_dimension"

        ("call_center_key", "cc_closed_date", "cc_open_date", "cc_name", "cc_class", "cc_employees",

        "cc_hours", "cc_manager", "cc_address", "cc_city", "cc_state", "cc_region")

        (
            select "call_center_key", "cc_closed_date", "cc_open_date", "cc_name", "cc_class", "cc_employees",

            "cc_hours", "cc_manager", "cc_address", "cc_city", "cc_state", "cc_region"

            from "update_call_center_dimension__dbt_tmp"
        );

테이블 materialization의 최적화 옵션

모델을 테이블로 materialize할 때 여러 최적화를 쓸 수 있어요. 각 config 파라미터는 생성된 CREATE TABLE DDL에 Vertica 특정 절을 적용해요.

자세한 내용은 Vertica options for table optimization을 참고하세요.

이런 최적화는 아래 예시처럼 모델 SQL 파일에서 구성할 수 있어요.

ORDER BY 절 구성

CREATE TABLE 문의 ORDER BY 절을 활용하려면 모델에서 order_by config 파라미터를 쓰세요.

order_by config 파라미터 사용

vertica_incremental.sql

{{ config(  materialized='table',  order_by='product_key') }}

        select * from public.product_dimension

vertica_incremental.sql (컴파일 결과)

create  table  "VMart"."public"."order_s__dbt_tmp" as

             ( select * from public.product_dimension)

                 order by product_key;

SEGMENTED BY 절 구성

CREATE TABLE 문의 SEGMENTED BY 절을 활용하려면 모델에서 segmented_by_string 또는 segmented_by_all_nodes config 파라미터를 쓰세요. 기본적으로 테이블을 세그먼트하는 데 ALL NODES가 사용되므로, segmented_by_string config 파라미터를 쓰면 SQL 문에 ALL NODES 절이 추가돼요. no_segmentation 파라미터로 ALL NODES를 비활성화할 수 있어요.

segmented by 절에 대해 더 알아보려면 여기를 확인하세요.

segmented_by_string config 파라미터 사용

segmented_by_string config 파라미터는 해시 세그먼테이션 같은 SQL 표현식으로 projection 데이터를 세그먼트하는 데 쓰일 수 있어요.

vertica_incremental.sql

{{ config( materialized='table', segmented_by_string='product_key'  )  }}

        select * from public.product_dimension

vertica_incremental.sql (컴파일 결과)

create  table

        "VMart"."public"."segmented_by__dbt_tmp"

        as (select * from public.product_dimension)

             segmented by product_key  ALL NODES;

segmented_by_all_nodes config 파라미터 사용

segmented_by_all_nodes config 파라미터는 모든 클러스터 노드에 분산시키기 위해 projection 데이터를 세그먼트하는 데 쓰일 수 있어요.

참고: segmented_by_all_nodes 파라미터를 전달하려면 segmented_by_string 파라미터를 전달해 테이블을 세그먼트해야 해요.

vertica_incremental.sql

{{ config( materialized='table', segmented_by_string='product_key' ,segmented_by_all_nodes='True' )  }}

            select * from public.product_dimension

vertica_incremental.sql (컴파일 결과)

create  table   "VMart"."public"."segmented_by__dbt_tmp" as

          (select * from public.product_dimension)

            segmented by product_key  ALL NODES;

UNSEGMENTED ALL NODES 절 구성

CREATE TABLE 문의 UNSEGMENTED ALL NODES 절을 활용하려면 모델에서 no_segmentation config 파라미터를 쓰세요.

no_segmentation config 파라미터 사용

vertica_incremental.sql

{{config(materialized='table',no_segmentation='true')}}

          select * from public.product_dimension

vertica_incremental.sql (컴파일 결과)

create  table
                      "VMart"."public"."ww__dbt_tmp"

                   INCLUDE SCHEMA PRIVILEGES as (

                select * from public.product_dimension )

                        UNSEGMENTED ALL NODES ;

PARTITION BY 절 구성

CREATE TABLE 문의 PARTITION BY 절을 활용하려면 모델에서 partition_by_string, partition_by_active_count, partition_by_group_by_string config 파라미터를 쓰세요.

partition by 절에 대해 더 알아보려면 여기를 확인하세요.

partition_by_string config 파라미터 사용

partition_by_string (선택)은 테이블 데이터 파티셔닝이 일어나는 기준이 되는 특정 column_name 하나의 문자열 값을 받아요.

vertica_incremental.sql

{{ config( materialized='table', partition_by_string='employee_age' )}}

        select * FROM public.employee_dimension

vertica_incremental.sql (컴파일 결과)

create table "VMart"."public"."test_partition__dbt_tmp" as

        ( select * FROM public.employee_dimension);

        alter table "VMart"."public"."test_partition__dbt_tmp"

        partition BY employee_age

partition_by_active_count config 파라미터 사용

partition_by_active_count (선택)은 이 테이블에 몇 개의 파티션이 활성인지 지정해요. 정수 값을 받아요.

참고: partition_by_active_count 파라미터를 전달하려면 partition_by_string 파라미터를 전달해 테이블을 파티셔닝해야 해요.

vertica_incremental.sql

{{ config( materialized='table',
    partition_by_string='employee_age',
    partition_by_group_by_string="""
                                  CASE WHEN employee_age < 5 THEN 1
                                  WHEN employee_age>50 THEN 2
                                  ELSE 3 END""",

    partition_by_active_count = 2) }}

      select * FROM public.employee_dimension

vertica_incremental.sql (컴파일 결과)

create  table "VMart"."public"."test_partition__dbt_tmp" as

      ( select * FROM public.employee_dimension );

          alter table "VMart"."public"."test_partition__dbt_tmp" partition BY employee_ag

            group by CASE WHEN employee_age < 5 THEN 1

        WHEN employee_age>50 THEN 2

        ELSE 3 END

        SET ACTIVEPARTITIONCOUNT 2  ;

partition_by_group_by_string config 파라미터 사용

partition_by_group_by_string 파라미터(선택)은 각 그룹 케이스를 단일 문자열로 지정하는 문자열을 받아요.

이것은 partition_by_string 값에서 파생돼요.

partition_by_group_by_string 파라미터는 파티션을 별도의 파티션 그룹으로 병합하는 데 쓰여요.

참고: partition_by_group_by_string 파라미터를 전달하려면 partition_by_string 파라미터를 전달해 테이블을 파티셔닝해야 해요.

vertica_incremental.sql

{{config(materialized='table',
    partition_by_string='number_of_children',
    partition_by_group_by_string="""
                                  CASE WHEN number_of_children <= 2 THEN 'small_family'
                                  ELSE 'big_family' END""")}}
select * from public.customer_dimension

vertica_incremental.sql (컴파일 결과)

create  table "VMart"."public"."test_partition__dbt_tmp"  INCLUDE SCHEMA PRIVILEGES as

        ( select * from public.customer_dimension ) ;

      alter table "VMart"."public"."test_partition__dbt_tmp"
      partition BY number_of_children
      group by CASE WHEN number_of_children <= 2 THEN 'small_family'
                                             ELSE 'big_family' END  ;

KSAFE 절 구성

CREATE TABLE 문의 KSAFE 절을 활용하려면 모델에서 ksafe config 파라미터를 쓰세요.

vertica_incremental.sql

{{  config(  materialized='table',    ksafe='1'   ) }}

          select * from  public.product_dimension

vertica_incremental.sql (컴파일 결과)

create  table "VMart"."public"."segmented_by__dbt_tmp" as

        (select * from  public.product_dimension )
            ksafe 1;

더 알아보기 (Learn more)