DBT governance
Thid markdown document will specify the rules that need to follow by every developer.
Short naming converntion lists that need to follow
| model_type Shortcut | Full name |
|---|---|
| seed | Seed |
| src | Source |
| snap | Snapshot |
| stg | Stage |
| int | Intermediate |
| fct | Fact |
| dim | Dimension |
| rep | Report |
| sem | Semantic |
| model_name Shortcut | Full name | Use case |
|---|---|---|
| brg | Brigde | relationship table |
| log | Log | log data |
CIEF General Rule
- Snowflake SQL use to write dbt SQL code
- Star schema is use
- First week of the day is start at Monday, and last week of the day will be Sunday
- Fiscal 1st quarter is start from Febuary
- Timezone: Kuala Lumpur / Malaysia (GMT +8)
- Some status/type is not input in raw database (You should found in seed)
DBT Rule
Structure of the dbt model layer
- Analyses
- Analyses layer will not create in Snowflake
- You can write some adhoc queries
- Test some SQL code before write in Models
- Macros
- Jinja function that reuse in other models
- Models
-
Staging
- System name
- Materialise:
View - 1-to-1 relationship (or mapping) to source tables.
- Column renaming
- Column remove
- Column data renaming, such as (status integer to string)
- Data input error cleansing
- Check for raw data freshness
- Data type transformation
- Data split and merge
- Source
- Source will write in YML
- Check Freshness
- Check duplicate id
- Check null id
- Materialise:
- System name
-
Intermediate
- Materialise:
Ephemerally - Stacking layers of logic with clear and specific purposes to prepa our staging models to join into the entities we want
- Be referenced repeatedly in more than one model
- Isolating complex operations
- Materialise:
-
Marts/warehouse
- Materialise:
Table - Store fact and dimension models
- Materialise:
-
Marts/reporting
- Materialise:
Table - Store custom reports
- Materialise:
-
- Seeds
- Store custom dataset in csv format
- The dataset must not change frequently
- Snapshots
- DBT build-in SCD type 2 function
- Prefer to use after the source table and before the staging layer
- Tests
- Can write some yml test case
File Naming Rules
- File names must be unique
- Each sql/python file must start with [
model_type]_[system_name]__[model_name]s.sql/py - The model should be name as plural. (eg: stg_exchange__orders.sql)
Column Naming Rules
-
If array datatype, the column naming must be plural (eg: ids, messages)
-
Schema, table and column names should be in
snake_case. -
Limit use of abbreviations that are related to domain knowledge. An onboarding employee will understand
current_order_statusbetter thancurrent_os. -
Use names based on the business terminology, rather than the source terminology.
-
Each model should have a primary key that can identify the unique row, and should be named
<object>_id, e.g.account_id– this makes it easier to know whatidis being referenced in downstream joined models. -
If a surrogate key is created, it should be named
<object>_sk. -
For
baseorstagingmodels, columns should be ordered in categories, where identifiers are first and date/time fields are at the end.
Example:transformed as ( select -- ids order_id, customer_id, -- dimensions order_status, is_shipped, -- measures order_total, -- date/times created_at, updated_at, -- metadata _sdc_batched_at from source ) -
Date/time columns should be named according to these conventions:
-
Timestamps:
<event>_datetime
Example:created_datetime -
Dates:
<event>_date
Example:created_date
-
-
Booleans should be prefixed with
is_orhas_.
Example:is_active_customerandhas_admin_access -
Price/revenue fields should be in decimal currency (e.g.
19.99for $19.99; many app databases store prices as integers in cents). If non-decimal currency is used, indicate this with suffix, e.g.price_in_cents.
SQL Coding Rule
- The SQL clause must be UPPERCASE (eg.
SELECT,FROM,WHERE,GROUP BY,LIMIT,WITH,AS,SUM,PARTITION OVER,DIV0,LEFT JOIN,ON....) - Try to avoid using
EXCLUDEin the SQL - Avoid using multi layer subquery, and try to use CTE, subquery must not more than 1 layer
- Each model structure must contain with
--IMPORT
WITH [table_names] AS (
SELECT * FROM {{ ref('file_names')}}
),
--LOGIC
[logic_names] AS (
.....
),
--FINAL
final__[table_names] AS (
)
SELECT * FROM final__[final_table_names]
Testing
- At a minimum,
uniqueandnot_nulltests should be applied to the expected primary key of each model.