Problem:

Projekt w którym uczestniczę ma dwie gałęzie. Jedna odpowiada za data engineering, druga za data science. Ta druga część zespołu do zbudowania modelu wnioskującego potrzebuje tylko przyrostu danych. Nie potrzebują tych danych, które się nie zmieniły. Interesują ich tylko zmieniające się dane.
Inżynierowie danych są częścią zupełnie innego obozu. Zależy im na dostarczaniu zawsze wszystkich danych. Według nich tak jest szybciej, spójniej, nie trzeba wykrywać co zostało usunięte lub zmienione. Łatwiej modyfikować layout danych w tym schemacie: dodawać lub usuwać kolumny, zmieniać typy danych.
Jak pogodzić te dwa światy?

Rozwiązanie:

Ładowanie całościowe jest mniej problematyczne ale trzeba zadbać o jakość danych (data quality). To ważny punkt do zaadresowania z data inżynierami. Przy okazji jak zrobili już całościowy load do warstwy brązowej (bronze). Niech przygotują widoki, które będą pokazywała deltę czyli tylko to co się zmieniło. Żeby ułatwić liczenie delty każdy wiersz wystawiony do warstwy bronze przez źródło będzie posiadał własny podpis (hash, md5, xxhash64)

Wady ładowania przyrostowego

Warto wspomnieć na początku, że danych jest relatywnie mało. To nie są dane transakcji z kart kredytowych. Największa tabela zajmuje 10 GB.

Wydaje się, że obliczenie delty jest szybsze? Wystawianie tylko zmienionych rekordów i w zależności od scenariusza tylko wstawianie lub aktualizowanie danych.

Aktualizowanie tabeli jest kosztowne, przeszukiwanie tabeli i wyszukiwanie odpowiedniego klucza.

Chcesz sprawdź sam. Merge, który aktualizuje i dodaje wiersze, jest bardziej kosztowny (czas + compute) od takiego scenariusza, gdy tylko wstawiamy dane.

Ładowanie przyrostowe to też wyzwania: co robić z rekordami, które zostały usunięte w źródle. Czy dodawać flagę is_deleted i potem używać ją w filtrach? Czy interesuje nas przechowywanie historii usuniętych rekordów? Jeżeli nie to ładowanie przyrostowe (incremental load) to nie jest polecany scenariusz.

Jeżeli nadal chcemy zaznaczyć co się zmieniło możemy to zrobić również przy ładowaniu całościowym.

W jaki sposób zaprojektować warstwę bronze?

W warstwie bronze spodziewasz się prostych tabel odwzorowujących to co jest w systemie źródłowym:

customer
order
transaction
market_hierarchy

Nic nie stoi na przeszkodzie, żeby mieć te tabele ale z datą jako sufiksem i codziennie dodawać nowe tabele:

customer_20260519
order_20260519
transaction_20260519
market_hierarchy_20260519
customer_20260520
order_20260520
transaction_20260520
market_hierarchy_20260520

Konsumpcja danych z warstwy bronze może się odbywać przez widoki odbudowywanie codziennie, które odwołują się do ostatniej załadowanej dzisiaj wersji:

v_customer_full
v_order_full
v_transaction_full
v_market_hierarchy_full

Lub tylko danych przyrostowych:

v_customer_incr
v_order_incr
v_transaction_incr
v_market_hierarchy_incr

Przykład wyznaczenia delty

Stwórzmy sobie dwa widoki pomocnicze, które będą odtwarzane codziennie. Jeden będzie wskazywał na dane, które zostały załadowane dzisiaj:

create or replace view trsales_dm_plab.z_d_unit_act as
select * from trsales_dm_plab.z_d_unit_20250523;

Drugi będzie pomazywał to co zostało załadowane wczoraj, to pomocniczy widok służący tylko do wyliczenia delty:

create or replace view trsales_dm_plab.z_d_unit_prev as
select * from trsales_dm_plab.z_d_unit_20250522;

Przyrost będziemy wykrywać na podstawie tego, czego nie było we wczorajszym ładowaniu danych albo tego, co zostało zmienione w porównaniu z dniem poprzednim.

create or replace view trsales_dm_plab.z_d_unit_incr as
select act.* from trsales_dm_plab.z_d_unit_act act
left join trsales_dm_plab.z_d_unit_prev prev on act.unit_tk = prev.unit_tk
where prev.unit_tk is null or act.checksum != prev.checksum

Pytania projektowe

Możesz się zapytać:

Jak długo trzymamy takie tabele?

Czy nie wystarczy nam time travel, po co tworzyć nowe wersje tabel?

Może wystarczy trzymać dzienne migawki danych (snapshoty) w tej samej tabeli.

Twoja architektura może mieć inne założenia. Wtedy przyjmiesz inny model danych, natomiast deltę możesz policzyć nie wchodząc w szczegóły implementacyjne. Czy to będzie jedna tabela przechowująca dzienne snapshoty danych czy będą te tabele tworzone w trybie dziennym.

Można też rozważyć, czy nie interesuje Cię na przykład stan danych na koniec albo początek miesiąca. Takie snapshoty miesięczne mogą być czasami pomocne.

Jakie zadania utrzymaniowe?

Tabel z dziennymi migawkami danych nie chcesz trzymać w nieskończoność. Nikogo nie interesuje historia. Interesuje nas tylko stan obecny. Ewentualnie co się zmieniło od wczoraj.

Usuwanie starych tabel raz w miesiącu może być zbyt rzadkie. Raz w tygodniu w sobotę brzmi jak dobry pomysł.