๐ ELT์ ๋ฏธ๋
-
ETL์ ๊ฒฐ๊ตญ ELT๋ฅผ ํ๊ธฐ ์ํจ์ด๋ค. ์ด ๋ ๋ฐ์ดํฐ ํ์ง ๊ฒ์ฆ์ด ์ค์ํ๋ค.
-
๋ฐ์ดํฐ ํ์ง์ ์ค์์ฑ ์ฆ๋
-
๋ฐ์ดํฐ ํ์ง ์ ์ง -> ๋น์ฉ/๋
ธ๋ ฅ ๊ฐ์์ ์์ฐ์ฑ ์ฆ๋์ ์ง๋ฆ๊ธธ
๐ DB Normalization
-
DB๋ฅผ ์ข๋ ์กฐ์ง์ ์ด๊ณ ์ผ๊ด๋ ๋ฐฉ๋ฒ์ผ๋ก ๋์์ธํ๋ ค๋ ๋ฐฉ๋ฒ
-> DB ์ ํฉ์ฑ์ ์ฝ๊ฒ ์ ์งํ๊ณ ๋ ์ฝ๋๋ค์ ์์ /์ญ์ /์ ์ฌ๋ฅผ ์ฉ์ดํ๊ฒ ํ๋ ๊ฒ
-
Normalization์ ์ฌ์ฉ๋๋ ๊ฐ๋
- Primary Key
- Composite Key
- Foreign Key
-
1NF(First Normal Form)
- ํ ์
์๋ํ๋์ ๊ฐ๋ง ์์ด์ผํ๋ค. (atomicity)
- Primary Key๊ฐ ์์ด์ผํ๋ค.
- ์ค๋ณต๋ ํค๋ ๋ ์ฝ๋๋ค์ด ์์ด์ผํ๋ค.
-> ์ฆ ๋ชฉํ๋ ์ค๋ณต์ ์ ๊ฑฐํ๊ณ atomicity๋ฅผ ๊ฐ๋ ๊ฒ์ด๋ค.
- 2NF(Second Nomal Form)
- 1NF๋ฅผ ๋ง์กฑ
- Primary Key๋ฅผ ์ค์ฌ์ผ๋ก ์์กด ๊ฒฐ๊ณผ๋ฅผ ์ ์ ์์ด์ผํ๋ค.
- ๋ถ๋ถ์ ์ธ ์์กด๋๊ฐ ์์ด์ผ ํ๋ค.
- ์ฆ ๋ชจ๋ ๋ถ๊ฐ ์์ฑ๋ค์ Primary Key๋ฅผ ๊ฐ์ง๊ณ ์ฐพ์ ์ ์์ด์ผํ๋ค.
-> ์ค๋ณต์ ์ ๊ฑฐํ๊ณ atomicity๋ฅผ ๊ฐ๋ ๊ฒ์ด ๋ชฉํ์ด๋ค.
- 3NF(Third Normal Form)
- 2NF๋ฅผ ๋ง์กฑ
- ์ ์ด์ ๋ถ๋ถ ์ข
์์ฑ์ด ์์ด์ผํ๋ค.
-
Data Build Tool
- ELT์ฉ ์คํ์์ค : In-warehouse data transformation
- DBT Labs๋ผ๋ ํ์ฌ๊ฐ ์์ฉํํจ
- Analytics Engineer๋ผ๋ ๋ง์ ๋ง๋ค์ด ๋๋ค.
-
๋ค์ํ ๋ฐ์ดํฐ ์จ์ดํ์ฐ์ค๋ฅผ ์ง์
- Redshift, Snowflake, Bigquery, Spark
-
ํด๋ผ์ฐ๋ ๋ฒ์ ๋ ์กด์ฌํ๋ค.
-
DBT๊ฐ ์ง์ํ๋ ๋ฐ์ดํฐ ์์คํ
- BigQuery
- Redshift
- Snowflake
- Spark
- ...
- DBT ๊ตฌ์ฑ ์ปดํฌ๋ํธ
- ๋ฐ์ดํฐ ๋ชจ๋ธ(models)
- ํ
์ด๋ธ๋ค์ ๋ช ๊ฐ์ ํฐ์ด๋ก ๊ด๋ฆฌํ๋ค.
-> ์ผ์ข
์ CTAS(SELECT ๋ฌธ๋ค), Lineage ํธ๋ํน
- Table, View, CTE ๋ฑ๋ฑ
- ๋ฐ์ดํฐ ํ์ง ๊ฒ์ฆ(tests)
- ์คํญ์ท(snapshots)
๐ DBT ์ฌ์ฉ ์๋๋ฆฌ์ค
- Production DB์ ์ ์ฅ๋๋ ์ ๋ณด๋ค์ Data Warehouse๋ก ์ ์ฌํ๋ค๊ณ ๊ฐ์
- raw_data.user_event
- ์ฌ์ฉ์/๋ ์ง/์์ดํ
๋ณ๋ก impression์ด ์๋ ๊ฒฝ์ฐ ๊ทธ ์ ๋ณด๋ฅผ ๊ธฐ๋ก
- impression์ผ๋ก๋ถํฐ ํด๋ฆญ, ๊ตฌ๋งค, ๊ตฌ๋งค์ ๊ธ์ก์ ๊ธฐ๋ก
- ์ค์ ํ๊ฒฝ์์๋ ์ด๋ฐ aggregate ์ ๋ณด๋ฅผ ๋ก๊ทธ ํ์ผ๋ฑ์ ์์ค๋ก๋ถํฐ ๋ง๋ค์ด๋ด๋ ํ๋ก์ธ์ค๊ฐ ํ์ํ๋ค.
CREATE TABLE raw_data.user_event(
user_id int,
datestamp timestamp,
item_id int,
clicked int,
purchased int,
paidamountint
);
- raw_data.user_variant
- ์ฌ์ฉ์๊ฐ ์์ํ AB test variant๋ฅผ ๊ธฐ๋กํํ์ผ(control vs. test)
CREATE TABLE raw_data.user_variant(
user_id int,
variant_id varchar(32)
);
CREATE TABLE raw_data.user_metadata(
user_id int,
age varchar(16),
gender varchar(16)
);
Fact Table
- ๋ถ์์ ์ด์ ์ด ๋๋ ์์ ์ ๋ณด๋ฅผ ํฌํจํ๋ ์ค์ ํ
์ด๋ธ
- ์ผ๋ฐ์ ์ผ๋ก ๋งค์ถ ์์ต, ํ๋งค๋, ์ด์ต๊ณผ ๊ฐ์ ์ธก์ ํญ๋ชฉ์ด ํฌํจ๋๋ค.
- ๋น์ฆ๋์ค ๊ฒฐ์ ์ ์ฌ์ฉ๋๋ค.
- Fact ํ
์ด๋ธ์ ์ผ๋ฐ์ ์ผ๋ก ์ธ๋ ํค๋ฅผ ํตํด ์ฌ๋ฌ Dimension ํ
์ด๋ธ๊ณผ ์ฐ๊ฒฐ๋๋ค.
- ๋ณดํต Fact ํ
์ด๋ธ์ ํฌ๊ธฐ๊ฐ ํจ์ฌ ๋ ํฌ๋ค.
Dimension Table
- Fact ํ
์ด๋ธ์ ๋ํ ์์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ํ
์ด๋ธ
- ๊ณ ๊ฐ, ์ ํ๊ณผ ๊ฐ์ ํ
์ด๋ธ๋ก Factํ
์ด๋ธ์ ๋ํ ์์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค.
- Fact ํ
์ด๋ธ์ ๋ฐ์ดํฐ์ ๋งฅ๋ฝ์ ์ ๊ณตํ์ฌ ๋ค์ํ ๋ฐฉ์์ผ๋ก ๋ถ์ ๊ฐ๋ฅํ๊ฒ ํด์ค๋ค.
- Dimension ํ
์ด๋ธ์ Primary Key๋ฅผ ๊ฐ์ง๋ฉฐ, Factํ
์ด๋ธ์์ ์ฐธ์กฐํ๋ค.(Foreign Key)
- ๋ณดํต Dimension ํ
์ด๋ธ์ ํฌ๊ธฐ๋ ํจ์ฌ ๋ ์๋ค.
์ต์ข
์์ฑ ๋ฐ์ดํฐ (ELT Table)
SELECT
varian_id,
ue.user_id,
datestamp,
age,
gender,
COUNT(DISTINCT item_id) num_of_items,
COUNT(DISTINCT CASE WHEN clicked THEN item_id END) num_of_clicks,
SUM(purchased) num_of_purchases,
SUM(paidamount) revenue
FROMraw_data.user_event ue
JOIN raw_data.user_variant uv ON ue.user_id = uv.user_id
JOIN raw_data.user_metadata um ON uv.user_id = um.user_id
GROUP BY 1, 2, 3, 4, 5;
๐ DBT ์ค์น/ํ๊ฒฝ์ค์
- ์ฌ์ฉ์ ์ฐจ
- dbt ์ค์น
- dbt Cloud vs. dbtCore
- git์ ๋ณดํต ์ฌ์ฉํ๋ค.
-> pip install dbt-redshift
-> dbt-core ๋ชจ๋๋ ๊ฐ์ด ์ค์น๋๋ค.
- dbt ํ๊ฒฝ์ค์
- Connector ์ค์
- Connector๊ฐ ๋ฐ๋ก ๋ฐํ์ด ๋๋ ๋ฐ์ดํฐ ์์คํ
(Redshift, Spark, ...)
- ๋ฐ์ดํฐ๋ชจ๋ธ๋ง(tier)
- Raw Data -> Staging -> Core
- ํ
์คํธ ์ฝ๋ ์์ฑ
- Snapshot ์ค์
-
์ค์น
- pip install dbt-redshift
-> ์ฌ๊ธฐ์ ๋ง์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ค.. ํ๋์ฉ ๋ฐ๋ผํด๋ณด์.
- sudo apt-get update
- get-pip.py ์ค์น
- pip ์ค์น ๋๋ ํ ๋ฆฌ๋ฅผ PATH์ ์ถ๊ฐํ๊ธฐ
- nano ~/.bashrc
- ๋งจ ์๋์ ์๋ ์ฝ๋ ์์ฑ
- export PATH=$PATH:/home/urface/.local/bin
- urface ๋์ ๋น์ local์ด๋ฆ ์์ฑ
- source ~/.bashrc (์ ์ฅ)
- pip3 --version (ํ์ธ)
- PostgreSQL ์ค์น
- sudo apt-get install postgresql libpq-dev
- gcc๋ฑ ํ์ ๋๊ตฌ ์ค์น
- sudo apt-get install build-essential
- ๋ง์ฝ psycopg2 ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์๋ ๋ช
๋ น์ด ์
๋ ฅ
- pip3 install --user psycopg2-binary
- Python ๊ฐ๋ฐํจํค์ง
- sudo apt-get install python3-dev
- DBT - Redshift ์ค์น
- pip install --user dbt-redshift
-
ํ๊ฒฝ ์ค์
- dbt๋ผ๋ ๋๋ ํ ๋ฆฌ๋ฅผ ํ๋ ๋ง๋ค๊ณ ์งํํ์.
- init์ผ๋ก ํ๊ฒฝ์ค์ ์ ์งํํด์ฃผ์.
- ํ์ธํด๋ณด์.
- ls -tl dbt_name

- dbt_project.yml๊ณผ profiles.yml ํ์ผ์ ์ค์ํ๋ค.
-
dbt ํ์ผ๊ณผ ํด๋
- dbt_project.yml : ๋ฉ์ธ ํ๊ฒฝ ์ค์ ํ์ผ
- models
- seeds
- tests
- snapshots
- macros
- analyses
- README.md
-
dbt_project.yml
- name
- version
- config-version
- profile
- ์๋ ๋ด์ฉ์ ํด๋ ์ด๋ฆ๋ค๊ณผ ์ผ์นํด์ผํ๋ค.
- model-paths:["models"]
- analysis-paths:["analyses"]
- test-paths:["tests"]
- seed-paths:["seeds"]
- macro-paths:["macros"]
- snapshot-paths:["snapshots"]
- target-path: "target" -> ๊ฒฐ๊ณผ๋ค์ด ์ ์ฅ๋๋ ํด๋
- clean-targets:
- models:
- ์ฌ๊ธฐ์ example์ดํ 2์ค์ ์ญ์ ํ๋ฉฐ models์ ์๋ example ์๋ธํด๋๋ ์ญ์ ํ๋ค.
-
dbt_profiles.yml
- Project_name
- dev:
- dbname
- host
- password
- port
- schema
- threads
- type
- user
- target : dev
๐ DBT Model
1. Model์ด๋?
- ELT ํ
์ด๋ธ์ ๋ง๋ฌ์ ์์ด์ ๊ธฐ๋ณธ์ด ๋๋ ๋น๋ฉ๋ธ๋ก์ด๋ค.
-> Table, View, CTE์ ํํ๋ก ์กด์ฌํ๋ค.
- ์
๋ ฅ, ์ค๊ฐ, ์ต์ข
ํ
์ด๋ธ์ ์ ์ํ๋ ๊ณณ์ด๋ค.
- Tier(raw, staging,core,...)
- raw => staging(src) => core
2. View๋?
- SELECT ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ง ๊ฐ์ ํ
์ด๋ธ
- ๊ธฐ์กด ํ
์ด๋ธ์ ์ผ๋ถ ํน์ ์ฌ๋ฌ ํ
์ด๋ธ๋ค์ ์กฐ์ธํ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณตํ๋ค.
- CREATE VIEW ์ด๋ฆ AS SELECT ...
- View์ ์ฅ์
- ๋ฐ์ดํฐ์ ์ถ์ํ : ์ฌ์ฉ์๋ View๋ฅผ ํตํด ํ์ ๋ฐ์ดํฐ์ ์ง์ ์ ๊ทผํ๋ค.
- ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์ ํ์๊ฐ ์๋ค.
- ๋ฐ์ดํฐ๋ณด์ : View๋ฅผ ํตํด ์ฌ์ฉ์์๊ฒ ํ์ํ ๋ฐ์ดํฐ๋ง ์ ๊ณตํ๋ค.
- ์๋ณธ๋ฐ์ดํฐ ์ ๊ทผ ๋ถํ์
- ๋ณต์กํ ์ฟผ๋ฆฌ์ ๊ฐ์ํ : SQL(View)๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ๋จ์ํํ๋ค.
- View์ ๋จ์
- ๋งค๋ฒ ์ฟผ๋ฆฌ๊ฐ ์คํ๋๋ฏ๋ก ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์๋ค.
- ์๋ณธ ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ ๋ชจ๋ฅด๋ฉด ์คํ์ด ์คํจํ๋ค.
3. Model ๊ตฌ์ฑ์์
- Input
- ์
๋ ฅ(raw)๊ณผ ์ค๊ฐ(staging, src)๋ฐ์ดํฐ ์ ์
- raw๋ CTE๋ก ์ ์
- staging์ View๋ก ์ ์
- Output
- ์ต์ข
(core) ๋ฐ์ดํฐ ์ ์
- core๋ Table๋ก ์ ์
- model ํด๋ ์๋ sql ํ์ผ๋ก ์กด์ฌ
- ๊ธฐ๋ณธ์ ์ผ๋ก๋ SELECT + Jinja ํ
ํ๋ฆฟ๊ณผ ๋งคํฌ๋ก
- ๋ค๋ฅธ ํ
์ด๋ธ๋ค์ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.(reference)
-> ์ด๋ฅผ ํตํด ๋ฆฌ๋์ง ํ์
WITH src_user_evernt AS(
SELECT * FROM raw_data.user_event
)
SELECT
user_id,
datestamp,
item_id,
clicked,
purchased,
paidamount
FROM
src_user_event
- models/sec/src_user_metadata.sql
WITH src_user_metadata AS(
SELECT * FROM raw_data.user_metadata
)
SELECT
user_id,
age,
gender,
updated_at
FROM
src_user_metadata
- models/sec/src_user_variant.sql
WITH src_user_variant AS(
SELECT * FROM raw_data.user_variant
)
SELECT
user_id,
variant_id
FROM
src_user_variant
5. Model Building : dbt run

6. Model Building Check
- ํด๋น ์คํค๋ง ๋ฐ์ ํ
์ด๋ธ ์์ฑ ์ฌ๋ถ ํ์ธ
- dbt run์ ํ๋ก์ ํธ์ ๋ค์ํ SQL์ ์คํํ๋ค.
-> ์ด SQL๋ค์ DAG๋ก ๊ตฌ์ฑ๋์๋ค.
- dbt run์ ๋ณดํต ๋ค๋ฅธ ๋ ํฐ ๋ช
๋ น์ ์ผ๋ถ๋ก ์คํํ๋ค.
- dbt test
- dbt docs generate
7. Model ๊ตฌ์ฑ - output
-
Materialization
- ์
๋ ฅ ๋ฐ์ดํฐ(Table)๋ค์ ์ฐ๊ฒฐํ์ฌ ์๋ก์ด ๋ฐ์ดํฐ(Table)์ ์์ฑํ๋ ๊ฒ์ด๋ค.
-> ๋ณดํต ์ฌ๊ธฐ์ ์ถ๊ฐ transformation์ด๋ ๋ฐ์ดํฐ clean-up์ ์ํํ๋ค.
- 4๊ฐ์ง์ ๋ด์ฅ materialization์ด ์ ๊ณต๋๋ค.
- ํ์ผ์ด๋ ํ๋ก์ ํธ๋ ๋ฒจ์์ ๊ฐ๋ฅํ๋ค.
- dbt run์ ๊ธฐํ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง๊ณ ์คํํ๋ค.
-
Materialization ์ข
๋ฅ
- View
- ๋ฐ์ดํฐ๋ฅผ ์์ฃผ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ
- Table
- ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณตํด์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
- Incremental (Table Appends)
- Fact Table
- ๊ณผ๊ฑฐ ๋ ์ฝ๋๋ฅผ ์์ ํ ํ์๊ฐ ์๋ ๊ฒฝ์ฐ
- Ephemeral(CTE)
- ํ SELECT์์ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ํ ํ๋๋ฐ ์ฌ์ฉํ๋ค.
WITH src_user_variant AS(
SELECT * FROM {{ ref('src_user_variant') }}
)
SELECT
user_id,
variant_id
FROM
src_user_variant
- models/dim/dim_user_metadata.sql
-> ์ค์ ์๋ฐ๋ผ view/table/CTE ๋ฑ์ผ๋ก ๋ง๋ค์ด์ ์ฌ์ฉ๋๋ค.
-> meterialized๋ผ๋ ํค์๋๋ก ์ค์ ํ๋ค.
WITH src_user_metadata AS(
SELECT * FROM {{ ref('src_user_metadata') }}
)
SELECT
user_id,
age,
gender,
updated_at
FROM
src_user_metadata
- models/fact/fact_user_event.sql
-> Incremental Table๋ก ๋น๋ (materialized = 'incremental')
{{
config(
materialized = 'incremental',
on_schema_change='fail'
)
}}
WITH src_user_event AS (
SELECT * FROM {{ ref("src_user_event") }}
)
SELECT
user_id,
datestamp,
item_id,
clicked,
purchased,
paidamount
FROM
src_user_event
WHERE datestamp is not NULL
{% if is_incremental() %}
AND datestamp> (SELECT max(datestamp) FROM {{ this }})
{% endif %}
-
incremental_strategy๋ ์ฌ์ฉ๊ฐ๋ฅ
- append
- merge
- insert_overwrite
->์ด ๊ฒฝ์ฐ unique_key์ merge_update_columns ํ๋๋ฅผ ์ฌ์ฉํ๊ธฐ๋ ํจ
-
์คํค๋ง๊ฐ ๋ฐ๋ ๊ฒฝ์ฐ ๋์ ๋ฐฉ๋ฒ ์ง์
- append_new_columns
- ignore
- sync_all_columns
- fail
-
model์ materialized format ๊ฒฐ์
- ์ต์ข
Core Table๋ค์ View๊ฐ ์๋ Table๋ก ๋น๋ํ๋ค.
- dbt_project.yml ํธ์ง
-
dbt compile vs. dbt run
- dbt compile : SQL ์ฝ๋๊น์ง๋ง ์์ฑ, ์คํX
- dbt run : ์์ฑ๋ ์ฝ๋๋ฅผ ์ค์ ์คํํ๋ค.
