haulwork.yaml ehk kuidas kirjeldada laadimine

Laadimisülesande definitsioon on YAML struktuuriga tekstifail, mis tavaliselt viitab ka SQL-failidele, mis asuvad samas kasutas. Definitsioon võib sisaldada ka infot, millise versiooninumbrini peab olema tulem-tabel viidud ja versioonini viimiseks leiab SQL-failid "ver" alamkaustast.

Definitsioonifailis saab määrata päevaaja, mil laadimine võib toimuda (tööaja eelne aeg alates südaööst, tööaeg, tööajajärgne aeg kuni südaööni) ning sagedusintervalli (vaikimisi kõigil ülesannetel 23 tundi). Sageduse saab andmebaasitasemel "üle kirjutada" tabelise meta.bis_reconf (ajutisena, või tööhüpoteesidena, et hiljem täiendada definitsioonifaili lõppväärtusega).

Iga laadimine võib olla kas kahesammuline (lähtebaasist tekstifaili ja tekstifailist tulembaasi (ODS-skeemi)) või ühesammuline (tulembaasist tulembaasi, nt teise skeemi teise tabelisse andmete transformatsiooniks, nt varjestamiseks või agregeerimiseks).

Täiendavalt võib lisada laadmisse jätkusamme. Üldjuhul on jätkusammudeks vastloodud tabelitele indeksite loomine.


haulwork.yaml

Deklaratsioon

Definitsioon algab "keele" deklareerimisega (struktuuri formaat ja versioon), milleks on bis.haulwork versioon 2, ning laadimisülesande unikaalse Id-ga

structure:
   format: bis.haulwork
   version: 2
id: inner.haridus.dim_kool

Laadimisülesande ID koosneb punkteraldatult kolmest osast:

  1. Teekond, ehk meta.bis_route tabeli kirje kood (need on: "from_arno", "inner")
  2. Sihtskeem, milleks on töötlemata andmete korral ODS-skeem (nt "ods_arno") ja töödeldud andmete korral valdkonna skeem (nt "haridus", "personal", "myyk")
  3. Sihttabel

Üheski komponendis ei tohi olla tühikuid, punkte, ülakomasid, jutumärke ega muid "pahasid" kirjamärke, sh ka mitte täpitähti (st mitte-ASCII märke). Kasutada läbivat väiketähte.


Käivitatavus

Järgnevad staatus (active vs old), sõltvused ja automaatkäivituse info

status: active
depends:
 - from_arno.ods_arno.haridusasutus
 - from_man.ext_muu.varvikood
 - inner.dwh_global.dim_aadress
run:
   keep_pause: 15 hours
   morning: false
   workhours: false
   evening: true

Kui status = old, siis esimesel korral, kui laadimiste juhtija (Haulmanager) seda näeb, siis ta teeb viimase versioneerimise (kui on sellel määratud versioneeritavus ehk olemas alamkaust "ver") ja eemaldab seejärel laadimisülesande registrist ja seega seda kunagi rohkem ei täideta. Kui keskkonnas vähemalt üks tsükkel on läbitud, siis võib selles  keskkonnas lähtefaili (kausta) eemaldada. Soovitus eemalda kood alles pärast seda, kui "old" on jõudnud livesse.

Kui definitsioonifailis on algusest peale (tema esimesel nägemisel laadimiste juhtija poolt) status = old, siis teda registrisse ei kantagi (ja versioneerimise võimalust ignoreeritakse).


Laadimisülesanne pannakse tööjärjekorda vastavalt "run" ja "depends" infole.

Üldjuhul ei ole mõistlik kasutada mõlemat varianti. Kui tegu on sõltuva laadimisega, siis pole mõtet teda ajaliselt käivitada (inner-laadimised ehk teisendused sõltuvad üldjuhul allikbaasidest, allikbaasidest laadmised panna ajaliselt käima).

Sõltuvad laadimised ignoreerivad run sektsiooni, st päevaaegasid. Kui sõltar (master) tabel on laetud, siis on BIs eesmärk laadida ASAP ära sõltuvad tabelid.

P.S. Kui mõtlesid välja, et läbi sõltuvuste võib mõni laadimisülesanne sattuda tööjärjekorda mitu korda, siis mõtlesid õigesti. Aga muretseda pole vaja – laadimisülesande täitmise alguses kontrollitakse, et ega teda pole tagapool veel tulemas, ning kui on, siis jäetakse seekordne vahele (skip).


Intervall (keep_pause) peab olema esitatud kui PostgreSQL intervall tüüp ('1 days', '24 hours', '15 minutes' jne, vt vajadusel PostgreSQL manuali), ilma ülakomadeta (vt näidet üleval).

Päevaosad on defineeritud järgnevalt:

  1. morning - aeg südaööst kuni 8:00-ni (07:59:59.999)
  2. workhours - 8:00 - 18:00 (17:59:59.999)
  3. evening - 18:00 kuni südaöö (23:59:59.999)


Sammud

Põhitöö teevad ära "aktsioonid" ehk ehitusklotsid, milles saab viidata ka SQL-failidele.

actions:
 - do: shadow
   input: input.sql # create table as sisu select, ilma semikoolonita, üks käsk
   hash_before: hash_before.sql
   hash_after: hash_after.sql
   after: after.sql # indeksite tegemine tulemtabelile, kommentaari loomine
   pkcol: # siinkohal võib PK olla deklareeritud paksemana kui ta tegelikult on (ma pakun, et mida täpsemalt see siin vastab elule, seda kiirem/õigem)
    - id
 - do: runsql
   file: 
    - comments.sql
    - indicies.sql

Kui viidatakse failile (file: input.sql), siis fail peab olemas olema (definitsioonidega samas kasutas) ja peab sisaldama vähemalt ühte SQL käsku. Kõik elemendid, mis viitavad aktsioonides failidele, on lubatud kasutada ka mitut faili (YAML massiiv), aga on olukordi, kus teisi peale esimese ignoreeritakse (nt shadow aktsioonis on input fail osa tervikust (embeditakse) ja seda saab olla ainult üks).


Võimalikud aktsioonid

AktsioonTegevus
shadowSuurte tulemtabelite loomine andmebaasi sees olevate andmete põhjal. Soovituslik alternatiiv "map" tegevusele.
mapTulemtabeli tekitamiseks andmebaasis juba olemasolevate tabelite põhjal (st andmete teisendus) ühe SQL SELECT abil
runSQL käivitamine ilma mingite kõrvalefektideta (ilma väärtust lisavate automaatsete lisategevusteta).
init

Välisest allikast suurte tabelite alglaadimiseks, kui on võimalus saada allikast select käsuga sorteeritult ja limiteeritult ning kuni laadimine pole lõppenud, ei lisandu allikasse andmeid vahele (sorteerimise mõttes)

eksportAllikbaasist välja eksport (faili või otse tulembaasi) kasutades teadmisi alliktabeli muudatuste timestamp veergude olemasolust.
importFailist sissetõmbamine tulemtabelisse (fail asub BIS masinas, st loodi sinna eksport abil)
timelineMuudatuste tuvastamine andmelao tabelis võrreldes eelmise kontrolliga


Tulemtabeli vesioneerimine

Mõned aktsioonid teevad alati ise ja täpselt õige struktuuriga tulemtabeli (map, shadow). Seal ei ole versioneerimine teemaks.

Teised aga eeldavad, et tulemtabel on loodud (ja mõned eeldavad ka konkreetseid lisavälju). Ja kui tabel on eelnevalt loodud, siis võib olla vaja ka teda muuta (struktuuri muutmine, seotud objektide (indeksid) lisamine).

Registrisse saab kirja tulemtabeli hetke versioon (alguses on 0). Kui on olemas alamkaust "ver", siis selles olevate failide nimedest (nt 001.sql) loetakse välja täisarvud, sorteeritakse ja vaadatakse, kas on mõni suurem senisest. Suuremad käivitatakse ja versiooninumbrit registris tõstetakse.

Kui midagi olulist muutub lähtebaasis (nt lisati oluline veerg) ja see on vaja saada ka ODS-i, siis on vaja lisada ALTER TABLE käsuga SQL-fail alamkausta ver. Failinimi teha 0-täitmisega (nt kujul 007.sql ja 011.sql), et koodipuus oleks failid kenasti järjestatud (7 eespool kui 11). Kui lisada uus versioonifail, siis manager teeb asap versioneerimise ära (vahest juba koodiuuenduse järgse levitamise käigus).


Versioneerimisega käib kaasas andmelaos oleva tabeli tühjendamine (ja laadimise muudatusaja tagasikeeramine aegade algusse, kui on selline mõiste). Seega andmed kaovad ja on vaja kõik uuesti laadida. Kui selleks muudatuseks oli veeru lisamine, siis polegi midagi parata, see on normaalne soovitud käitumine. Aga kui muudatus oli veeru eemaldamine või indeksi tegemine või kommentaari tegemine või veerutüübi muutmine nii, et andmed saavad alles jääda (nt varchar(100) → varchar(200)), siis saab eraldi direktiiviga märku anda, et andmeid see muudatus tabelis ei mõjuta ja tabeli tühjendamist ei tehta.

upgrade_nondata: # need ver kausta all olevad versioonid (int!), mis ei tekita vajadust selle tabeli laadimisega otsast alata
  - 5 # varchar -> text
  - 6 # indeksid