Databricks: Delta Live Tablesit ovat uusi ja siisti juttu

Databricks: Delta Live Tablesit ovat uusi ja siisti juttu
Kirjoittanut Jimi Bergskaug
27.11.2023 - Lukuaika 15 min
Databricks
Delta Live Tables
Data Lakehouse
Data technologies
DLT

Intro

Tämän blogikirjoituksen aiheena ovat Databricksin Delta Live Tablesit. Niillä latauksia rakentaessa kaikki pääsevät helpommalla. Pahimpien syntaksi- (ei missään nimessä käyttäjä-) peräisten töyssyjen jälkeen olen ollut suorastaan iloisesti yllättynyt niiden käytettävyydestä. Katsotaan seuraavaksi porukalla mitä ne oikein ovat ja mitä niillä tekee.

Mikä on Delta Live Tables?

Databricks julkaisi Delta Live Tablesit (tuttavallisemmin ja jatkossa DLT) jokin aika sitten. Ne ovat uusi deklaratiivinen tapa määritellä ja toteuttaa ELT/ETL putkia Databricksissä. DLT on vielä osittain Previewissä, mikä näkyy joinain puuttuvina, tai hassusti toimivina ominaisuuksina. Tutustutaan yksityiskohtiin vähän myöhemmin.

Mitä tässä blogissa on?

Käydään läpi DLT:n pääasiat: eri komponentit, joita siinä hyödynnetään, orkestrointi, erot muihin lähestymistapoihin ja sen sellaista. Sen jälkeen esittelen pienen demon, jonka rakensin meidän Databricksiin. Käydään syntaksia läpi ja eri tapoja luoda lataukset. Katsotaan lopuksi muutamat haasteet, joihin me ollaan törmätty näillä DLT palikoilla rakennellessa.

Tarkemmin DLT:stä

Mitä meinaa Declarative?

Ensimmäisenä pistää silmään taikasana deklaratiivinen, joka erottaa DLT:n perinteisestä ELT/ETL latauksesta, jota voisi kutsua proseduaaliseksi (tai netin mukaan voi). Eli ennen vanhaan määriteltiin vaihe vaiheelta tarkalleen, miten lataus pitää suorittaa:

  • ota uusin tiedosto file storagesta (eli katso jostain aputaulusta minkä päivän tiedostot ladattiin viimeksi ja hae sitten sitä päivää isommat tiedostot) tai API:sta,
  • jos jotain pitää päivittää tai mergetä, looppaa päivitykset läpi niin monta kertaa kuin tässä satsissa on päiviä ja avaimia
  • ja ainiin, muista luoda taulu ensin
  • ja muista raahata mukana joko avainta josta tunnistetaan uudet rivit seuraavassa vaiheessa tai tyhjentele tauluja latausten jälkeen

DLT:n kanssa keskitytään määrittelemään mikä lopputuloksen pitäisi olla. DLT hoitaa tylsät hommat, kuten uusien rivien tunnistamisen, optimoinnin, orkestroinnin, muutoksien hallinnan, taulujen luonnin ja niin edelleen.

Lähteet

Lähteiden osalta DLT tottelee aika lailla samoja tiedostotyyppejä kuin muutkin keinot. Hieno puoli on se, että samoilla latauksilla pystyy periaatteessa käsittelemään sekä streamaavaa, että batchisatsidataa. DLT osaa myös hyödyntää AutoLoaderia, jolla saadaan lähdetiedostoja luettua tosi näppärästi niin, että napataan aina vain uudet tiedostot. Latauksissa voidaan viitata saman Pipelinen tauluihin taikka Databricksin muihin tauluihin.

Kielistä

DLT taulut luodaan kirjoittamalla notebookkeja joko SQL:llä tai Pythonilla. Sellainen rajoitus on olemassa, että notebookit voivat sisältää joko pythonia tai SQL:lää. Toki kehittäjä voi luoda useamman notebookin jos kieliä pitää jostain syystä sekoittaa.

Syntaksista

Sekä Pythonilla että SQL:llä tehtäessä DLT kehittämisessä on tietty syntaksi ja lausekkeet. Voidaan luoda streamaavia tauluja, materialisoituja näkymiä ja näkymiä. DLT tauluja luovia ja käsitteleviä notebookkeja ei pysty ajamaan interaktiivisesti suoraan notebookista, vaan ne pitää kytkeä DLT Pipelineen, joka taas ei toimi, jos notebookkien sisältö ei ole syntaksisesti oikein. Dokumentaatio on vähintäänkin epäjohdonmukainen ja vajaavainen, mutta ihan vilkaisun arvoinen. Kyllä sillä alkuun pääsee, mutta esimerkiksi välttämättä ei kerrota molemmilla kielillä, miten jokin objekti luodaan.

Objekteista

DLT kyselyissä voidaan luoda kolmenlaisia tauluja tai näkymiä. Syntyvä datatarjotin riippuu siitä, miten kyselynsä kirjoittaa. CREATE STREAMING LIVE TABLE luo streamaavan taulun, CREATE LIVE TABLE tai APPLY CHANGESin hyödyntäminen luokin table sanasta huolimatta materialisoidun näkymän ja CREATE (STREAMING) LIVE VIEW luo näkymän.

Orkestrointi

Yksi DLT:n näppärimmistä puolista on UI, jonka Databricks tarjoaa, kun DLT notebook kytketään Workflow:hun. DLT tunnistaa itse riippuvuudet ja luo niistä kuvauksen, josta voidaan seurata, kun ajo etenee, paljonko rivejä siirtyi ja niin edelleen. Workfloweja hyödyntämällä voidaan ajaa useampi DLT pipeline peräkkäin, tai välissä vaikka jotain muuta, jos siltä tuntuu.

Pipelinet voidaan ajastaa, tai laittaa käyttämään jotain triggeriä, esimerkiksi tiedoston saapumista. Toki myös on mahdollista asettaa pipeline olemaan aina päällä, ja siirtämään dataa saapumistahtiin.

Klustereista

DLT pipelinejä ajaessa DLT hoitaa klusterien luomisen, skaalaamisen ja sammuttamisen. Klusterien ja nodejen määrään ja tyyppiin saa toki puuttua jos siltä tuntuu. DLT pipelinejen ajamisessa voidaan käyttää Developement tai Production Modea, joista ensimmäisessä käytetään yhtä clusteria ajoihin. Production modessa DLT käyttää klusteria jokaista päivitystä varten, jolloin ne ovat eristettyjä toisistaan. Aina on myös käytössä yksi klusteri, jota käytetään ylläpitoon.

Hinnoittelusta

DLT pipelinet voidaan määritellä käyttämään yhtä kolmesta tuoteversiosta "Product Edition", joissa on vähän eri kyvykkyyksiä. Jos haluaa vain siirtää dataa, matalin taso riittää hyvin. Jos halutaan esimerkiksi tehdä CDC-juttuja tai käyttää automaattista datan laadun seurantaa, pitää ottaa kukkaroa vähän lisää esiin.

Myöskin se, että ajetaanko pipeline jostain liipaisimesta kerran, vai onko se päällä koko ajan, luonnollisesti vaikuttaa kerrytettyihin kustannuksiin. Hinnoista ei kannata tekstin kuranttiuden varmistamiseksi hirveästi kirjoittaa.

Kirjoitan vähän silti, mutta varaan väistämättömyyden muutoksiin. Voimassa olevat hinnat löytää googlaamalla. Ne lasketaan Databriksin valuutassa eli DBU:ina. Halvin Azuren tuoteversio maksaa kirjotushetkellä 0.3 dollaria per yksikkö. Kallein versio maksaa 0.54 dollaria per yksikkö. Yksi worker käyttää vähän yli yhden DBU:n tunnissa. Eli ihan hirveän kalliista touhusta ei ole kyse.

Streamauksesta

Seuraavana tulevassa demossa ei streamausta käsitellä lainkaan. Mainittakoon siitä silti jotain. DLT tukee erilaisia streamauslähteitä, ja jopa useamman lähteen yhdistämistä samaan tauluun samassa latauksessa.

Demosta

Ladataan lähteestä vähän dataa Databricksiin. Lähteenä toimii meidän Azuren Blob Storage. Haetaan raakana paria eri tiedostotyyppiä. Tommin Arduino on Tampereella, joten streamausdataa ei tällä kertaa oteta. Se on kuvakaappauksina ihan yhtä tylsän näköistä kuin batchidata. Muokataan dataa vähän ja ladataan ne bronze ja silver -kerroksiin. Jätetään goldi nyt tekemättä, koska mallintaminen on tämän demon aihealueen ulkopuolella.

Loin mallidatat juttelemalla vähän ChatGPT:n kanssa. Esimerkkinä toimii nyt Data Clinicin kuvitteellinen sivubisnes, Cake Clinic, joka myy leivonnaisia Helsingin alueella. Latasin datat meidän Azure Blog Storageen.

Osa tiedostoista on CSV- ja osa JSON-muodossa. Tämä demo olettaa, että käyttöoikeudet sun muut on jo laitettu kuntoon Databricksissä. Vinkkinä toki, että me käytetään Managed Identity -mallia.

Tuotteet edustaa SCD2 tyyppistä tuotedataa, johon tulee päivityksiä. Tilaukset on transaktionaalista dataa joka kuvastaa meidän mahtavasti vetävää kroisanttikauppaa.

Lataan osan datasta SQL:kielellä ja osan Pythonilla.

Tiedostot Azuren Blob Storagessa.

Tiedostot kansiossa. Numeroidut tiedostot lisättiin oikeasti vasta myöhemmin.

Bronze

Okei ja ei muuta kun asiaan. Tiedostot ovat nyt varastossa ja aloitetaan lataamalla ne Databricksiin. Otetaan ensimmäiseksi tilausdata ja käytetään sen lataamiseen SQL:kieltä ja Autoloaderia.

Taulujen määritykseen voidaan lisätä esimerkiksi partitiontisäännöt, erikseen määritelty tallennussijainti ja kommentteja taulusta tai yksittäisistä sarakkeista (jos schema määritellään). Laitoin mukaan nyt myös latausajan, jos sitä johonkin joskus tarvitsisi, sekä lähdetiedoston nimen.

Bronzen tilaustiedoston lukemiskoodi.

Nyt kun taulu on määritelty, lataus on melkein valmis. Seuraavaksi annetaan Delta Live Tables Pipelinelle tämä koodi ja ajetaan se.

Luodaan uusi DLT pipeline Workflows-alueella. Laitetaan pipeline modeksi Triggered, eli se käynnistetään joko itse tai jostain liipaisimesta. Jos dataa tulisi vaikka vähän tipotellen koko ajan, tai käytettäisiin striimauslähteitä, silloin modeksi kannattaisi laittaa Continuous. Toki silloin klusterit hurisivat koko ajan ja touhu kävisi kalliimmaksi. Tarkan markan datanhamstraaja siis välttelee sitä jos vaan voi.

Valitaan lähdekoodi, eli tässä tapauksessa yllä näkyvä scripti, joka on notebookissa "bronze DLT SQL". Kätevää on se, että me voimme laittaa lähteeksi myös useamman notebookin, jos vaikka halutaan tehdä tauluille tai aihealueille omat notebookit.

Meillä käytetään tietenkin Unity Catalogia, johon kävin tekemässä cakeclinic katalogin. Jos schemaa ei ole etukäteen määritelty, se luodaan, kun sille vaan antaa tässä nimen. Hyvä käytäntö latauksissa on määritellä schema esimerkiksi medaljongin vaiheen mukaan.

Workflows-alueen yläreuna, josta löytyy Create pipeline -nappi.

Annetaan pipelinelle jokin kuvaava nimi. Käytetään nyt Product Editionina Advancedia, koska jossain välissä saatetaan lisätä datan laatuun liittyvää käsittelyä. Eli tässä tehdään cakeclinic catalogin bronze schema. Clustereiden osalta en lähtenyt säätämään mitään. Autoscalingin max workerit rajasin myös yhteen varoiksi.

Pipelinen luontinäkymä.

Ajetaanpa tämä pipeline. Ja näin meillä on ensimmäiset datat databricksissä.

DLT Pipeline UI.

Haetaanpa lisää dataa. Ladataan seuraavaksi tuotetietoja. Niin kuin oli puhetta, DLT latauksia voidaan määritellä myös Pythonilla. Ladataan tuotetiedot siis sillä.

Bronzen tuotetiedostojen latauskoodi.

Lisätään tämä uusi koodi myös pipelineen. Tein sen omaan notebookkiinsa nimellä bronze DLT Python. Samassa notebookissa ei voi olla useampaa kieltä, kun ladataan DLT tauluja, mutta saman pipelinen sisällä kieliä voi olla useampi, kunhan ne ovat erillisissä notebookeissa. Jos samaan notebookin koittaa laittaa useampaa kieltä, DLT valitsee niistä pääkieleksi määritellyn ja jättää muut solut kylmästi huomiotta. Ilmoittaa siitä toki.

Notebookit DLT pipelinen määrityksissä.

Ajetaan pipeline nyt uudelleen. Ja hoplaa, meillä on nyt kaksi taulua. Raaka_tilaukset tauluun ei tullut enempää rivejä, koska fiksu DLT tunnisti, ettei sille ole uusia tiedostoja lähteessä.

DLT pipeline UI.

Yhtä hyvin olisi voinut purkaa tilausdatasssa olevat nested tiedot samalla kun ladataan ne tiedostovarastosta, mutta tehdään nyt vielä shown vuoksi toinen lataus, jossa puretaan data vielä kokonaan auki. Huomataan tässä stream(live.taulunNimi) syntaksi, jolla saadaan helposti viitattua saman pipelinen käsittelemään tauluun, ja saadaan taulusta vain uudet rivit. Explode funktio helposti täräytää nested-rakenteen hedelmät samalle tasolle. Viitataan aikaisempaan tauluun Stream(live.taulunNimi) -notaatiolla, koska taulu on samassa pipelinessä.

Bronzen koodi, jossa puretaan nested rakenteet tilausdatasta.

Ja näin saatiin vielä purettu data mukaan pipelineen.

Siirtyneet tilaukset.

Seuraava vaihe on ladata data silver tasolle ja vähän siivoilla sitä. Tässä vaiheessa voitaisiin myös luoda lisää surrogaattiavaimia sun muuta, mutta pidetään tämä demo nyt yksinkertaisena.

Silver

Tehdään silverille oma DLT pipeline, jotta saadaan siinä luodut taulut omaan schemaansa. Toki voisi ajaa kaiken samalla pipelinellä samaan schemaan ja nimetä taulut vaikka jotenkin schema_taulunnimi, mutta meillä suositaan tätä mallia. Ainoa mitä menettää on hieno pipeline graafi, jossa olisi kaikki taulut.

Näytän tässä vielä yhden kikan jota voidaan hyödyntää kun halutaan jostain syystä temppuilla käytettävillä kehityskielillä: tehdään notebook, joka käyttää Pythonia, mutta pyspark kirjaston spark.sql() funktiolla ajetaankin taulun muodostus SQL kielisenä. Pythonilla voi olla helpompi tehdä taulujen määrityksiä ja sääntöjä, mutta kyselyn luontiin SQL on ainakin omasta mielestä simppelimpi, joten tässä tälläinenkin hybridimalli.

Tässä kohtaa ei voida käyttää LIVE.taulunNimi notaatiota, koska pronssitason taulut eivät ole samassa pipelinessä. LIVE. notaatiota voidaan käyttää vain tauluihin, jotka määritellään samassa pipelinessä.

Silverin tilaustaulun koodi.

Tilausten latausten koodi.

Ladataan tuotteet SQL:llä ja käytetään yhtä DLT näppärimmistä ominaisuuksista: Apply changes -toimintoa, joka korvaa vanhan kunnon mergen. Ja hoitaa samalla CDC käsittelyt, jos ja kun sellaista haluaa tehdä. Mergeissähän on ihan hirveä kirjoittaminen. Ja kuvitellaan vielä, että pitäisi esimerkiksi käsitellä useampi päivitys samalle avaimelle ja historioida muutokset SCD2 tyyliin.. Huhhuh mikä operaatio, merge loopin sisällä. Kestää ja kestää ja näyttää pahalta.

Apply changes on näppärä, nopea ja kätevä. Annetaan vain avaimet, sekvensoinnille peruste ja kerrotaan mitä sarakkeita seurataan. Loput menee DEKLARATIIVISESTI pellin alla. Huomauttamatta ei voi tässä kohtaa jättää sitä, että Apply changesillä ei voi luoda uusia avaimia dataan. Surrogaattiavainten käyttöhän on määritelmällisesti osa tälläistä käsittelyä, joten se voidaan laskea pieneksi miinukseksi. Näppärä kaveri kuitenkin luo avaimet jo ennen tämän taulun luontia, joten ympäri ongelmasta onneksi pääsee.

Tuotteiden Apply Changes CDC -käsittely.

Orkestrointi

Nyt kun meillä on useampi DLT pipeline, ja haluttaisi ajaa ne peräkkäin automaattisesti, voidaan hyödyntää Databricksin normaaleja Workflow Jobeja. Ne ottavat notebookkien ja muiden härpäkkeiden lisäksi vastaan myös DLT pipelinejä. Luodaanpa siis jobi nimellä CakeClinicPipeline ja laitetaan sinne meidän pipelinet. Määritellään riippuvuudet ja sitten jobi on valmis ajettavaksi tarpeen tullen.

Laitoin mausteeksi myös jotain notebookkeja, jotta tästä näkee myös, miten voitaisiin tarpeen tullen ajaa samalla vauhdilla myös ihan normi notebookkeja. Nyt tämä jobi voitaisiin laittaa laukeamaan vaikka aina aamuisin, tai kun lähdekansioon tulee uusia tiedostoja ja niin edelleen.

Tavallinen Workflow Jobi, jossa notebookit ja DLT pipelinet.

Seuraava lataus

Dataahan pitää aina saada lisää. Tässä nousee esiin taas DLT:n helppous. Kun käytetään streaming mallisia tauluja, ne tunnistavat automaattisesti lähtekansioihin ja -tauluihin tulleet rivit. Ladataan vähän lisää tilauksia ja päivityksiä tuotteille ja katsotaan miten käy.

Lisäsin lähdekansioon kaksi CSV:tä jossa on päivityksiä tuotteisiin, ja yhden JSON tiedoston, jossa on uusia tilauksia. Niin vaan näppärästi saadaan uudet rivit käsiteltyä, vaikka tiedostot ovat kaikki samassa kansiossa aiheittain.

Bronzen uuden latauskierroksen tulokset.

Silverissä näyttää siltä, ettei tuotetietoihin siirtynyt mitään. Tämä samalla pitää, ja ei pidä paikkaansa. DLT tunnistaa, ettei tuotu uusia avaimia tauluun, koska lähdetiedostoissa ei tullut uusia tuotteita, vain päivityksiä olemassa oleviin.

Silverin uuden latauskierroksen tulokset.

Ja näin saadaan esimerkiksi silver.tuotteet -taulu hienosti historioituun kuntoon. Nähdään, että esimerkiksi Data Donitsi tuotteelle on tullut päivityksiä, joissa resepti on vaihtunut. Apply changes luo __START_AT ja __END_AT sarakkeet, joilla hallitaan voimassaoloa. Yksi rivi on voimassa ja muut on avattu ja suljettu oikeassa järjestyksessä.

Silver tuotteet taulun sisältö. Huomaa SCD2 tyylinen historiointi.

Tässä myös vilaus tilaukset -taulusta, joka ei tosin ole kovin kiinnostavan näköinen.

Silver tilaukset taulun sisältö.

Käydään datan laadun tarkkailu erikseen toisessa kirjoituksessa joskus. Jos se koskaan valmistuu, saattaapi linkki löyty myös tästä jostain läheltä.

Muita kikkoja (BONUS)

Jos jostain syystä pitää tyhjentää DLT Streaming taulu, vanha ystävämme truncate ei toimi. Delete from <taulun nimi> toimii hienosti.

Jos jostain syystä pitää luoda omia avaimia, yksi helppo tapa luoda niitä on käyttää taulun luonnissa scheman määrittelyä ja luoda sinne sarake, joka syntyy <sarakkeenNimi> bigint GENERATE ALWAYS AS IDENTITY -tyylillä. DLT osaa myös hienosti pellin alla pitää kirjaa avaimesta. Vaikka taulusta deletoisi kaikki rivit, se osaisi silti jatkaa oikeasta kohtaa. Alla screenshot.

Näin generoidaan avain taulun riveille.

Aggregaatioita (group by, sum jne) tehtäessä DLT haluaa ajaa lähdetaulusta kaiken datan (full load). Tämä voi olla epätoivottavaa, jos haluttaisiin esimerkiksi lähdetaulusta koota kyselyllä distinctit uudet avaimet tai vastaavaa. Yksi ympärinavigointivaihtoehto, jota itse käytimme, on käyttää latauksessa DLT välitaulua, johon ladataan kaikki rivit aikaisemmasta taulusta, ja tästä välitaulusta luetaan sitten aggregoitu data. Putken lopuksi lisätään normaali notebook jossa tyhjennetään välitaulut delete from -komennolla. Vähän kikkailua, mutta päästiin lopputulokseen kohtalaisen tehokkaasti.

Toki tämä välivaihe voitaisiin välttää vain lisäämällä kyselyyn jokin where avain not in kohdetaulu -tyyppinen lauseke. Mutta jos kuvitellaan, että tauluihin kerääntyy ajan mittaan valtavia määriä rivejä, ei ehkä ole hyvä idea joka latauksessa ajaa miljardiin riviin aggregaatioita huvikseen.

Loppusanat

Niin kuin näkyy, varsin näppärä työkalu on tämä DLT. Lataukset ovat yksinkertaisempia, kun tarvitaan vähemmän ylimääräistä tavaraa, kuten päättelyä siitä, mitä pitää ladata seuraavaksi tai mitä jos pitää samaa entiteettiä koskevaa dataa päivittää useamman kerran. Jotain kitkanpaikkoja toki löytyy, mutta tuotekin on aika uusi ja päivityksiä tulee säännöllisesti. Esimerkiksi viimeisen kehitystuokion ja tämän blogin näpyttelyn välillä on pipelinejen ajamisen valikkoon ilmestynyt "Validate" painike, jolla voi ajaa testit pipelinen koodiin, ilman että dataan kosketaan. Aika kätevää.

Koitin miettiä, että missä tilanteissa kannattaisi vaihtaa normaaleista latauksista DLT toteutuksiin. Varmaan päällimmäinen vaihtoehto olisi se, että haluaa saumattomasti yhdistää streaming- ja batchlatauksia. Toinen, itselle tutumpi vaihtoehto olisi se, että haluaa vaan päästä helpommalla. Ei muuta, kun kokeilemaan siis.

Tietenkään ihan lastenleikkiä tälläkään touhuaminen ei ole, vaikka tekstistä sen kuvan saisikin. Jos tuli lukiessa sellainen olo, että tätähän voisi meikäläinen/meikäläisen palkkanörtit alkaa kokeilemaan, me autetaan mielellämme. Joko näppiksen edessä tai olan takana, ihan kumpi vaan on kätevämpää. Yhteyttä saa esimerkiksi sähköpostilla.

Kiitti lukemisesta, terkuin

Jimi

Avainsanat:

Databricks,

Delta Live Tables,

DLT,

Data Lakehouse,

ELT,

ETL

Jimi Bergskaug
Jimi BergskaugData Engineer

Jimi on Data Engineer. Muita harrastuksia sportti ja videopelit.

Tilaa blogin uutiskirje

Saa ilmoitus sähköpostiisi uusista julkaisuistamme dataan ja teknologioihin liittyen

Data Clinic logo

Nosta liiketoimintasi uudelle tasolle

Yhteystiedot

+358 50 551 9293

Osoite

Siltasaarenkatu 12 C, 8. kerros

00530 Helsinki

Laskutus

Näkemystä datasi hyödyntämiseen

© 2024 Data Clinic Oy

Tämä sivusto käyttää evästeitä palveluiden toimittamisessa, käyttäjäkokemuksen parantamisessa ja liikenteen analysoinnissa