Get In Touch
Kadıköy, İstanbul
mail@oguzerdogan.com
Ph: +90 554 524 0164
Back

dbt Fundamentals – Pt.4 models, dbt ile veri modelleme

Selam, serinin daha önceki yazılarında analytics engineering, elt ve dbt’nin ne olduğundan bahsederek, BigQuery ile dbt-core entegrasyonunu yapmıştık. Bu yazımda ise dbt’nin ana hattını oluşturan modelleme kısmına bir giriş yapıyoruz.

Analytics alanında, modelleme süreci verilerin şekillendirilmesidir. Bu süreç, ham verilerinizden başlayarak son dönüşüm verilerinize kadar uzanır. Genellikle veri mühendisleri, kaynak verilerinizi temsil eden tabloları oluşturmakla sorumludur ve BI aracınızın sorgulayabileceği nihai tabloları oluştururlar.

dbt’de modeller, dbt projenizdeki SQL select ifadeleridir. Her biri, ham verilerinizi yavaş yavaş alarak ihtiyacınız olan son verilere dönüştüren bir modüler mantık parçasını temsil eder. Bu modeller, yalnızca dbt’nizdeki models klasöründe bulunan SQL dosyalarında yer alırlar.

Her model veri ambarınızda bir tabloya karşılık gelir, yani 1-1 ilişkilidir.

Serinin daha önceki yazılarında bahsettiğim gibi dbt’nin harika yanı, bir tablo veya görünüm olarak bir şeyler inşa etmek için tüm DDL veya DML bilgisine sahip olmanız gerekmez.

Bu modelin nasıl oluşturulacağını SQL dosyasının üst kısmında ya da ayrı bir YAML dosyasında yapılandırarak yapabilirsiniz. Yapmamız gereken, oluşturulacak tabloyu SELECT ifadeleri ile dbt’ye vermek.

Elinizdeki ham veriyi bir oyun hamuru gibi düşünebilirsiniz. dbt ile de bu oyun hamuruna şekiller vererek, final nesnemizi oluşturacağız.

İsterseniz hemen ilk modelimize bir göz atalım.

İlk Model

dbt proje dizinimde, models klasörünün altında customers adında bir klasör açıyorum ve ardından dim_customers.sql adında bir dosya oluşturuyorum.

Bu SQL dosyası artık bizim dim_customers tablomuzun model dosyası. Burada tanımlayacağımız SQL ifadeleri sonrası dbt sayesinde BigQuery üzerinde dim_customers adında bir tablo oluşacak.

Çalışmada kullanabileceğimiz örnek bir veri lazım.

Bu veriyi BigQuery’de Select sorgusu atarak dbt-tutorial.jaffle_shop.customers üzerinden alabilirsiniz.

SELECT * FROM dbt-tutorial.jaffle_shop.customers

Veri BigQuery’deki public datasetlere dahil olduğu için erişebiliyor olmalısınız.

⚠️ Bir önceki yazımda dataset lokasyonu olarak US seçmemizin sebebi buydu, eğer location kaynaklı bir hata alıyorsanız, dataset lokasyonunuzu US yapmayı deneyin.

dbt projemize dönecek olursak, SQL ifadelerimizi yazmaya başlayalım. dbt üzerinde genellikle CTE’ler ile ilerleyerek transform işlemrimizi uyguluyor ve nihai çıktıya ulaşmaya çalışıyoruz.

Customer verisine erişim

Bunun için ilk olarak dim_customers.sql içerisinde aşağıdaki şekilde bir customers CTE’si oluşturuyorum;

customers CTE:

with customers as (

    select
        id as customer_id,
        first_name,
        last_name

    from dbt-tutorial.jaffle_shop.customers

),

Customer’lara eriştik, şimdi de bu customerlara ait order bilgilerine erişelim. Bunun için de dbt-tutorial.jaffle_shop.orders tablosunu kullanacağız.

orders CTE:

orders as (

    select
        id as order_id,
        user_id as customer_id,
        order_date,
        status

    from dbt-tutorial.jaffle_shop.orders

),

Sipariş bilgilerini de aldık, ek olarak şu şekilde bir işlem yapmak istediğimizi düşünelim.

Her bir müşterinin, ilk, son ve toplam sipariş bilgilerini de tabloda gösterelim.

Bunun için de customer_orders adında bir CTE oluşturuyorum.

customer_orders CTE:

customer_orders as (

    select
        customer_id,

        min(order_date) as first_order_date,
        max(order_date) as most_recent_order_date,
        count(order_id) as number_of_orders

    from orders

    group by 1

),

ve final aşaması olarak bu CTE’leri birleştirmek kalıyor.

final CTE:

final as (

    select
        customers.customer_id,
        customers.first_name,
        customers.last_name,
        customer_orders.first_order_date,
        customer_orders.most_recent_order_date,
        coalesce(customer_orders.number_of_orders, 0) as number_of_orders

    from customers

    left join customer_orders using (customer_id)

)

final CTE mizi de oluşturduk. Fakat bu sorgular ile hala fiziksel bir çıktıya ulaşamıyoruz, çünkü bu final CTE’sine SELECT sorgusu atmalıyız. Yapacağımız işlem basit

select * from final

Buraya kadar olan tüm sorguları toparlayıp BigQuery üzerinde çalıştırırsak şu şekilde bir çıktı elde edeceğiz.

İşte bu SELECT sorguları ile hazırladığımız dim_customers tablosunu dbt üzerinde models altında bir sql dosyasında tanımlıyoruz. Belirlediğimiz model tanımlamalarına göre de dbt bunları bir tablo ya da view olarak veri ambarı tarafında oluşturuyor.

Modeli Çalıştırma

dim_customers.sql dosyasını hazırladıktan sonra çalıştırmak için:

dbt run -m dim_customers yazıyoruz.

dbt models klasörü altında customers/dim_customers.sql dosyasını bularak bunu çalıştıracak.

17:29:23 1 of 1 START sql view model dbt_tutorial.dim_customers ......................... [RUN] 

17:29:25 1 of 1 OK created sql view model dbt_tutorial.dim_customers .................... [CREATE VIEW (0 processed) in 2.26s]

Burada CREATE VIEW bilgisini görüyoruz. Bunun sebebi dbt’ye oluşacak yapının materialized tipini belirtmememiz. Bunu BigQuery üzerinde fiziksel bir tablo da yapabilirdik.

dbt’de şu anda 4 tane materialized tipi var. Bunlar;

  • table
  • view
  • incremental
  • ephemeral

Aşağıdaki bağlantıdan detaylı bilgiye erişebilirsiniz.

Materializations | dbt Developer Hub

Incremental ve ephemeral kısmını daha sonra başka bir yazıda ele alacağım.

Materialized Tipini Belirleme

Materialized tipini belirlemek için önümüzde iki seçenek mevcut.

  • Proje genelinde, bir project.yml dosyasında ya da
  • Model özelinde, ilgili modelin sql dosyasında kod bloğu olarak ekleyebiliriz.

Proje Genelinde Materialized Belirleme

dbt_project.yml içerisinde materialization tanımlama:

├── dbt_project.yml
├── models
│   └── customers
│       └── dim_customers.sql
├── seeds
├── snapshots
├── target
└── tests

En altta models kısmını aşağıdaki şekilde güncelliyorum. Bu sayede; dbt, customers altındaki tüm modelleri bir tablo olarak create edecek.

name: 'dbt_tutorial'
version: '1.0.0'
config-version: 2

...
...
...
...

models:
  dbt_tutorial:
    # Config indicated by + and applies to all files under models/example/
    customers:
			# materialize all models in models/customers as tables
      +materialized: table

Burada spesifik olarak bir dizin altındaki belirli bir modeli vermek isteseydik de aşağıdaki şekilde olacaktı;

models:
  dbt_tutorial:
    # Config indicated by + and applies to all files under models/example/
    customers:
      dim_customers:
				# materialize dim_customers as table
        +materialized: table

Model özelinde Materialized Belirleme

dim_customers.sql içerisinde materialization tanımlama:

dim_customers.sql dosyasını açıyorum ve en yukarıda sadece

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

jinja blokunu ekliyorum. Artık dbt bu modeli çalıştırdığı zaman sadece buradaki config ayarını dikkate alacak.

dim_customers.sql için oluşan full script şu şekilde:

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

with customers as (

    select
        id as customer_id,
        first_name,
        last_name

    from dbt-tutorial.jaffle_shop.customers

),

orders as (

    select
        id as order_id,
        user_id as customer_id,
        order_date,
        status

    from dbt-tutorial.jaffle_shop.orders

),

customer_orders as (

    select
        customer_id,

        min(order_date) as first_order_date,
        max(order_date) as most_recent_order_date,
        count(order_id) as number_of_orders

    from orders

    group by 1

),

final as (

    select
        customers.customer_id,
        customers.first_name,
        customers.last_name,
        customer_orders.first_order_date,
        customer_orders.most_recent_order_date,
        coalesce(customer_orders.number_of_orders, 0) as number_of_orders

    from customers

    left join customer_orders using (customer_id)

)

select * from final

dbt run ile modeli çalıştırıyorum.

💡 Şu an tek model olduğu için dbt run ile bir model çalışacak, spesifik olarak bir model çalıştırmak isteseydim dbt run -m dim_customers yazabilirdim.

BigQuery’deki karşılığına bakalım;

Şemaya bakalım, acaba date alanları string mi geldi yoksa dbt bunları da ayarladı mı

BigQuery üzerinde sorgu atarak dbt’nin oluşturduğu tabloyu inceleyelim;

Gördüğümüz gibi, normal bir analiz yapar gibi SELECT ifadelerimizi yazdık ve dbt’de run komutunu çalıştırdık. BiqQuery tarafında istediğimiz çıktı bir tablo olarak oluştu.

dbt’nin compile ettiği SQL kodunu incelemek istersek proje dizininde

Target – run – dbt_tutorial – models – customers altında dim_customers.sql dosyasını görebiliriz.

dbt’nin BigQuery tarafında çalıştırdığı kod ise şu şekilde:

create or replace table `dbt-tutorial-379917`.`dbt_tutorial`.`dim_customers`
    
    
    OPTIONS()
    as (
      with customers as (

    select
        id as customer_id,
        first_name,
        last_name

    from dbt-tutorial.jaffle_shop.customers

),

orders as (

    select
        id as order_id,
        user_id as customer_id,
        order_date,
        status

    from dbt-tutorial.jaffle_shop.orders

),

customer_orders as (

    select
        customer_id,

        min(order_date) as first_order_date,
        max(order_date) as most_recent_order_date,
        count(order_id) as number_of_orders

    from orders

    group by 1

),

final as (

    select
        customers.customer_id,
        customers.first_name,
        customers.last_name,
        customer_orders.first_order_date,
        customer_orders.most_recent_order_date,
        coalesce(customer_orders.number_of_orders, 0) as number_of_orders

    from customers

    left join customer_orders using (customer_id)

)

select * from final
    );

Şu ana kadar yaptıklarımız basit select işlemleriydi, incremental bir yapı oluşturmak istediğimizde dbt’nin faydalarına daha yakından şahit olabiliyoruz.

dbt bu hünerleriyle insanı gerçekten etkiliyor, arkasında çok güzel bir topluluk var. Bu sayede de farklı public eklentiler gelişebiliyor. İlerleyen yazılada bunlara da değineceğim.

İlk modelimizi bu şekilde yazdık ve çalıştırdık. Sonraki bölümde modelleri moduler olarak ele alacağız, şimdilik sağlıcakla!

Kaynaklar:

https://www.getdbt.com/

Son cümleyi yazarken çalıyordu:

Oğuz
Oğuz
http://www.oguzerdogan.com
Data Delivery Guy

Leave a Reply

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

We use cookies to give you the best experience. Cookie Policy