dbt 增量物化策略简单说明
dbt 物化模型是支持增量处理的,实际场景中基于增量的数据处理还是比较重要的,dbt 对于增量的处理会和一些因素有关系,比如数据大小,
可靠的unique_key 以及特定数据平台的支持incremental_strategy 策略可以对于特定adapter 支持配置
目前支持的增量策略
当然与实际上的adapter 是有关系的,但是了解有助于学习数据增量的一些处理,目前支持的策略append,merge,delete+insert,insert_overwrite
从dbt v1.6 开始,pg以及redshift 支持了merge 策略
策略配置说明
可以通过项目级别以及模型配置
- merge 策略配置
一般我们需要配置的是unique_key, dbt 会使用新指对于整个匹配到的行进行重写,一些数据库的adapter 支持配置merge_update_columns ,同时也可以进行merge_exclude_columns
的配置 - 其他测试配置
官方文档没有完整的介绍,但是可以结合源码学习,对于新版本是dbt-adapter 中 dbt/include/global_project/macros/materializations/models/incremental/strategies.sql 文件
策略对应的macro
了解策略对应的macro 可以方便学习以及进行改造
- append
get_incremental_append_sql - delete+insert
get_incremental_delete_insert_sql - merge
get_incremental_merge_sql - insert_overwrite
get_incremental_insert_overwrite_sql
append 参考处理
{% macro get_incremental_append_sql(arg_dict) %}
{% do return(some_custom_macro_with_sql(arg_dict["target_relation"], arg_dict["temp_relation"], arg_dict["unique_key"], arg_dict["dest_columns"], arg_dict["incremental_predicates"])) %}
{% endmacro %}
{% macro some_custom_macro_with_sql(target_relation, temp_relation, unique_key, dest_columns, incremental_predicates) %}
# get_quoted_csv 是dbt 包含的一个增量处理帮助maco
{%- set dest_cols_csv = get_quoted_csv(dest_columns | map(attribute="name")) -%}
insert into {{ target_relation }} ({{ dest_cols_csv }})
(
select {{ dest_cols_csv }}
from {{ temp_relation }}
)
{% endmacro %}
incremental_predicates
此配置属于一个过滤,对于数据量比较大,我们希望只处理特定范围的数据比较方便,此参数属于一个数组,可以配置比较多的过滤
参考配置
{{
config(
materialized = 'incremental',
unique_key = 'id',
cluster_by = ['session_start'],
incremental_strategy = 'merge',
incremental_predicates = [
"DBT_INTERNAL_DEST.session_start > dateadd(day, -7, current_date)"
]
)
}}
内部参考处理(DBT_INTERNAL_SOURCE以及DBT_INTERNAL_DEST 属于内部的一个实践命名)
merge into <existing_table> DBT_INTERNAL_DEST
from <temp_table_with_new_records> DBT_INTERNAL_SOURCE
on
-- unique key
DBT_INTERNAL_DEST.id = DBT_INTERNAL_SOURCE.id
and
-- custom predicate: limits data scan in the "old" data / existing table
DBT_INTERNAL_DEST.session_start > dateadd(day, -7, current_date)
when matched then update
when not matched then insert
with large_source_table as (
select * from {{ ref('large_source_table') }}
{% if is_incremental() %}
where session_start >= dateadd(day, -3, current_date)
{% endif %}
),
自定义策略
核心是对于物化的自定义,格式为 get_incremental_STRATEGY_sql STRATEGY 是自定义的策略名称,比如一个insert_only 的
注意对于自定义的策略dbt 是不关系内部处理的,核心是macro 的调用
{% macro get_incremental_insert_only_sql(arg_dict) %}
{% do return(some_custom_macro_with_sql(arg_dict["target_relation"], arg_dict["temp_relation"], arg_dict["unique_key"], arg_dict["dest_columns"], arg_dict["incremental_predicates"])) %}
{% endmacro %}
{% macro some_custom_macro_with_sql(target_relation, temp_relation, unique_key, dest_columns, incremental_predicates) %}
{%- set dest_cols_csv = get_quoted_csv(dest_columns | map(attribute="name")) -%}
insert into {{ target_relation }} ({{ dest_cols_csv }})
(
select {{ dest_cols_csv }}
from {{ temp_relation }}
)
{% endmacro %}
使用
{{ config(
materialized="incremental",
incremental_strategy="insert_only",
) }}
说明
实际业务中进行数据的增量处理是很有价值的,可以加速数据处理,同时有助于优化速度,但是只有合理的使用了策略才能包装数据的准确以及高效,同时官方对于不同
数据库的实现基本都已经分离了,可以参考源码学习
参考资料
https://docs.getdbt.com/docs/build/incremental-strategy#strategy-specific-configs
https://docs.getdbt.com/docs/build/incremental-strategy#custom-strategies
https://docs.getdbt.com/guides/create-new-materializations?step=3
https://discourse.getdbt.com/t/incremental-best-practices/11495
https://github.com/dbt-labs/dbt-redshift/tree/main/dbt/include/redshift/macros/materializations
https://github.com/dbt-labs/dbt-adapters/blob/main/dbt/include/global_project/macros/materializations/models/incremental/strategies.sql