メインコンテンツまでスキップ
バージョン: 2.1

DBT Doris Adapter

DBT(Data Build Tool) は ELT (extraction, loading, transformation) における T (Transform) の実行に特化したコンポーネントです - 「データ変換」の部分を担当します。 dbt-doris adapterはdbt-coreをベースに開発されており、mysql-connector-pythonドライバーに依存してdorisにデータを変換します。

git: https://github.com/apache/doris/tree/master/extension/dbt-doris

version

dorispythondbt-coredbt-doris
>=1.2.5>=3.8,<=3.10>=1.5.0<=0.3
>=1.2.5>=3.9>=1.8.0>=0.4

dbt-doris adapter 使用方法

dbt-doris adapter インストール

pipを使用してインストール:

pip install dbt-doris

バージョンを確認:

dbt --version

if command not found: dbt:

ln -s /usr/local/python3/bin/dbt /usr/bin/dbt

dbt-doris adapter プロジェクト初期化

dbt init 

ユーザーはdbtプロジェクトをinitするために以下の情報を準備する必要があります

namedefaultmeaning
projectプロジェクト名
databaseアダプターを選択するための対応する番号を入力
hostdorisホスト
port9030doris MySQL Protocol Port
schemadbt-dorisでは、databaseと同等、データベース名
usernamedorisユーザー名
passworddorisパスワード
threads1dbt-dorisでの並列度(クラスター性能に合わない並列度を設定すると、dbtの実行失敗リスクが高まります)

dbt-dorisアダプターの実行

dbt runのドキュメントについては、こちらを参照してください。 プロジェクトディレクトリに移動し、デフォルトのdbtモデルを実行します:

dbt run 

model:my_first_dbt_modelmy_second_dbt_model

これらはそれぞれtableviewとして具現化されます。 次に、dorisにログインしてmy_first_dbt_modelmy_second_dbt_modelのデータ結果とTable作成文を確認します。

dbt-doris adapter Materialization

dbt-doris Materializationは3つをサポートします:

  1. view
  2. table
  3. incremental

View

viewをmaterializationとして使用すると、Modelはcreate view as文を通じて実行されるたびにviewとして再構築されます。(デフォルトでは、dbtのmaterialization方法はviewです)

Advantages: No extra data is stored, and views on top of the source data will always contain the latest records.
Disadvantages: View queries that perform large transformations or are nested on top of other views are slow.
Recommendation: Usually start with the view of the model and only change to another materialization if there are performance issues. Views are best suited for models that do not undergo major transformations, such as renaming, column changes.

config:

models:
<resource-path>:
+materialized: view

または、model ファイルに記述します

{{ config(materialized = "view") }}

Table

table materialization モードを使用する場合、モデルは各実行時に create table as select ステートメントでTableとして再構築されます。 dbt の tablet materialization において、dbt-doris はデータ変更の原子性を保証するために以下の手順を使用します:

  1. 最初に一時Tableを作成します:create table this_table_temp as {{ model sql}}
  2. this_table が存在しないかどうか、つまり初回作成かどうかを判定し、rename を実行して一時Tableを最終Tableに変更します。
  3. 既に存在する場合は、alter table this_table REPLACE WITH TABLE this_table_temp PROPERTIES('swap' = 'False') を実行します。この操作はTable名を交換し、this_table_temp 一時Tableを削除できます。this は Doris のトランザクション機構を通じてこの操作の原子性を保証します。
Advantages: table query speed will be faster than view.
Disadvantages: The table takes a long time to build or rebuild, additional data will be stored, and incremental data synchronization cannot be performed.
Recommendation: It is recommended to use the table materialization method for models queried by BI tools or models with slow 運用 such as downstream queries and conversions.

config:

models:
<resource-path>:
+materialized: table
+duplicate_key: [ <column-name>, ... ],
+replication_num: int,
+partition_by: [ <column-name>, ... ],
+partition_type: <engine-type>,
+partition_by_init: [<pertition-init>, ... ]
+distributed_by: [ <column-name>, ... ],
+buckets: int | 'auto',
+properties: {<key>:<value>,...}

または、modelファイルに記述してください:

{{ config(
materialized = "table",
duplicate_key = [ "<column-name>", ... ],
replication_num = "<int>"
partition_by = [ "<column-name>", ... ],
partition_type = "<engine-type>",
partition_by_init = ["<pertition-init>", ... ]
distributed_by = [ "<column-name>", ... ],
buckets = "<int>" | "auto",
properties = {"<key>":"<value>",...}
...
]
) }}

上記の設定項目の詳細は以下の通りです:

itemdescriptionRequired?
materializedTableの実体化形式(Doris DuplicateTable)Required
duplicate_keyDoris DuplicateキーOptional
replication_numTableレプリカの数Optional
partition_byTableパーティション列Optional
partition_typeTableパーティションタイプ、rangeまたはlist。(デフォルト:RANGEOptional
partition_by_init初期化されたTableパーティションOptional
distributed_byTable分散列Optional
bucketsバケットサイズOptional
propertiesDorisTableプロパティOptional

Incremental

dbtの前回実行のインクリメンタルモデルの結果に基づいて、レコードがTableにインクリメンタルに挿入または更新されます。 dorisのインクリメントを実現する方法は2つあります。incremental_strategyには2つのインクリメンタル戦略があります:

  • insert_overwrite:doris uniqueモデルに依存します。インクリメンタルな要件がある場合、モデルのデータを初期化する際に実体化をincrementalとして指定し、集約列を指定して集約することでインクリメンタルデータカバレッジを実現します。
  • append:doris duplicateモデルに依存し、インクリメンタルデータのみを追加し、履歴データの変更は一切行いません。そのためunique_keyを指定する必要はありません。
Advantages: Significantly reduces build time by only converting new records.
Disadvantages: incremental mode requires additional configuration, which is an advanced usage of dbt, and requires the support of complex scenarios and the adaptation of corresponding components.
Recommendation: The incremental model is best for event-based scenarios or when dbt runs become too slow

config:

models:
<resource-path>:
+materialized: incremental
+incremental_strategy: <strategy>
+unique_key: [ <column-name>, ... ],
+replication_num: int,
+partition_by: [ <column-name>, ... ],
+partition_type: <engine-type>,
+partition_by_init: [<pertition-init>, ... ]
+distributed_by: [ <column-name>, ... ],
+buckets: int | 'auto',
+properties: {<key>:<value>,...}

または、modelファイルに記述してください:

{{ config(
materialized = "incremental",
incremental_strategy = "<strategy>"
unique_key = [ "<column-name>", ... ],
replication_num = "<int>"
partition_by = [ "<column-name>", ... ],
partition_type = "<engine-type>",
partition_by_init = ["<pertition-init>", ... ]
distributed_by = [ "<column-name>", ... ],
buckets = "<int>" | "auto",
properties = {"<key>":"<value>",...}
...
]
) }}

上記の設定項目の詳細は以下の通りです:

itemdescriptionRequired?
materializedTableのmaterialized形式(Doris Duplicate/UniqueTable)Required
incremental_strategyIncremental_strategyOptional
unique_keyDoris Unique keyOptional
replication_numTableレプリカ数Optional
partition_byTableパーティション列Optional
partition_typeTableパーティションタイプ、rangeまたはlist(デフォルト:RANGEOptional
partition_by_init初期化されたTableパーティションOptional
distributed_byTable分散列Optional
bucketsバケットサイズOptional
propertiesDorisTableプロパティOptional

dbt-doris adapter seed

seedは、csvなどのデータファイルをロードするために使用される機能モジュールです。ファイルをライブラリにロードしてモデル構築に参加させる方法ですが、以下の注意事項があります:

  1. Seedは生データのロード(例えば、本番データベースからの大きなCSVエクスポート)には使用すべきではありません。
  2. Seedはバージョン管理されるため、ビジネス固有のロジックを含むファイル(例えば、国コードのリストや従業員のユーザーID)に最適です。
  3. dbtのseed機能を使用したCSVのロードは、大きなファイルに対してはパフォーマンスが良くありません。これらのCSVをdorisにロードする場合はstreamloadの使用を検討してください。

ユーザーはdbtプロジェクトディレクトリ下のseedsディレクトリを確認し、その中にcsvファイルとseed設定ファイルをアップロードして実行できます

 dbt seed --select seed_name

一般的なseed設定ファイルの記述方法では、カラム型の定義がサポートされています:

seeds:
seed_name:
config:
schema: demo_seed
full_refresh: true
replication_num: 1
column_types:
id: bigint
phone: varchar(32)
ip: varchar(15)
name: varchar(20)
cost: DecimalV3(19,10)

使用例

View Modelサンプルリファレンス

{{ config(materialized='view') }}

select
u.user_id,
max(o.create_time) as create_time,
sum (o.cost) as balance
from {{ ref('sell_order') }} as o
left join {{ ref('sell_user') }} as u
on u.account_id=o.account_id
group by u.user_id
order by u.user_id

Table Model サンプルリファレンス

{{ config(materialized='table') }}

select
u.user_id,
max(o.create_time) as create_time,
sum (o.cost) as balance
from {{ ref('sell_order') }} as o
left join {{ ref('sell_user') }} as u
on u.account_id=o.account_id
group by u.user_id
order by u.user_id

Incremental model sample reference (duplicate mode)

duplicate modeでTableを作成します。データ集計は行わず、unique_keyは指定しません

{{ config(
materialized='incremental',
replication_num=1
) }}

with source_data as (
select
*
from {{ ref('sell_order2') }}
)

select * from source_data

インクリメンタルモデルサンプルリファレンス(uniqueモード)

uniqueモードでTableを作成し、データを集約する場合、unique_keyを指定する必要があります

{{ config(
materialized='incremental',
unique_key=['account_id','create_time']
) }}

with source_data as (
select
*
from {{ ref('sell_order2') }}
)

select * from source_data

Incremental model フル更新サンプルリファレンス

{{ config(
materialized='incremental',
full_refresh = true
)}}

select * from
{{ source('dbt_source', 'sell_user') }}

bucketing ルールの設定例

ここでbucketには auto または正の整数を設定でき、それぞれ自動bucketing と固定bucket数の設定を表します。

{{ config(
materialized='incremental',
unique_key=['account_id',"create_time"],
distributed_by=['account_id'],
buckets='auto'
) }}

with source_data as (
select
*
from {{ ref('sell_order') }}
)

select
*
from source_data

{% if is_incremental() %}
where
create_time > (select max(create_time) from {{this}})
{% endif %}

レプリカ数の設定例リファレンス

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

with source_data as (
select
*
from {{ ref('sell_order2') }}
)

select * from source_data

Dynamic partitionサンプルリファレンス

{{ config(
materialized='incremental',
partition_by = 'create_time',
partition_type = 'range',
-- The properties here are the properties in the create table statement, which contains the configuration related to dynamic partitioning
properties = {
"dynamic_partition.time_unit":"DAY",
"dynamic_partition.end":"8",
"dynamic_partition.prefix":"p",
"dynamic_partition.buckets":"4",
"dynamic_partition.create_history_partition":"true",
"dynamic_partition.history_partition_num":"3"
}
) }}

with source_data as (
select
*
from {{ ref('sell_order2') }}
)

select
*
from source_data

{% if is_incremental() %}
where
create_time = DATE_SUB(CURDATE(), INTERVAL 1 DAY)
{% endif %}

従来のパーティション・サンプル・リファレンス

{{ config(
materialized='incremental',
partition_by = 'create_time',
partition_type = 'range',
-- partition_by_init here refers to the historical partitions for creating partition tables. The historical partitions of the current doris version need to be manually specified.
partition_by_init = [
"PARTITION `p20240601` VALUES [(\"2024-06-01\"), (\"2024-06-02\"))",
"PARTITION `p20240602` VALUES [(\"2024-06-02\"), (\"2024-06-03\"))"
]
)}}

with source_data as (
select
*
from {{ ref('sell_order2') }}
)

select
*
from source_data

{% if is_incremental() %}
where
-- If the my_date variable is provided, use this path (via the dbt run --vars '{"my_date": "\"2024-06-03\""}' command). If the my_date variable is not provided (directly using dbt run), use the day before the current date. For the incremental selection here, it is recommended to directly use doris's CURDATE() function, which is also a common path in production environments.
create_time = {{ var('my_date' , 'DATE_SUB(CURDATE(), INTERVAL 1 DAY)') }}

{% endif %}

バッチ日付設定パラメータサンプルリファレンス

{{ config(
materialized='incremental',
partition_by = 'create_time',
partition_type = 'range',
...
)}}

with source_data as (
select
*
from {{ ref('sell_order2') }}
)

select
*
from source_data

{% if is_incremental() %}
where
-- If the my_date variable is provided, use this path (via the dbt run --vars '{"my_date": "\"2024-06-03\""}' command). If the my_date variable is not provided (directly using dbt run), use the day before the current date. For the incremental selection here, it is recommended to directly use doris's CURDATE() function, which is also a common path in production environments.
create_time = {{ var('my_date' , 'DATE_SUB(CURDATE(), INTERVAL 1 DAY)') }}

{% endif %}

Tableデータのカラム型と精度をカスタマイズするサンプルリファレンス

schema.yamlファイルでは、models内のcolumnsに対してdata_typeを以下のように設定します:

models:
- name: sell_user
description: "A dbt model named sell_user"
columns:
- name: user_id
data_type: BIGINT
- name: account_id
data_type: VARCHAR(12)
- name: status
- name: cost_sum
data_type: DECIMAL(38,9)
- name: update_time
data_type: DATETIME
- name: create_time
data_type: DATETIME

Access catalog sample reference

データカタログは、Dorisデータレイク機能内の異なるデータソースへの参照であり、Databaseの上に階層化されています。 dbt-doris組み込みMacros: catalog_sourceを通じてアクセスすることが推奨されます。

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

select *
-- use macros 'catalog_source' not macros 'source'
-- catalog name is 'mysql_catalog'
-- database name is 'dbt_source'
-- table name is 'sell_user'
from {{ catalog_source('mysql_catalog', 'dbt_source', 'sell_user') }}