MOC — dny 1 a 2
1. Představení Azure Databricks 2. Výběr a konfigurace compute 3. Objekty v Unity Catalogu 4. Zabezpečení Unity Catalogu 5. Governance Unity Catalogu 6. Datové modelování 7. Ingest dat
MOC — pokračování
8. Čištění a transformace dat 9. Data quality constraints · mimo osnovu 10. Datové pipelines 11. Lakeflow Jobs 12. Vývojový lifecycle · mimo osnovu 13. Monitoring a optimalizace
🏠 Rozcestník kurzu
Pod čarou — den 3
14. Průřez Microsoft Fabric 15. Power BI + Fabric + Databricks 16. Migrace z Oracle
🏠 Rozcestník kurzu
DP-750 · Kapitola 6

Datové modelování v Unity Catalogu

Ingesční nástroje, formáty tabulek, partitioning, SCD, temporal tabulky a liquid clustering
🗂 Datové modelování

Cíle kapitoly

  • Navrhnout ingesční logiku podle požadavků — zvolit mezi full, inkrementální, streaming a CDC extrakcí.
  • Vybrat vhodný ingesční nástroj (Lakeflow Connect, Auto Loader, COPY INTO, notebooky, deklarativní pipelines) a formát tabulky (Delta, Iceberg, Parquet).
  • Implementovat SCD Type 2 dimenzi pomocí MERGE se sledováním platnosti verzí.
  • Navrhnout temporal (history) tabulky s Change Data Feed a time travel pro audit a debugging.
  • Rozhodnout mezi managed a external tabulkami a mezi partitioningem, Z-ORDER a liquid clusteringem.
6.1

Návrh ingesční logiky a konfigurace datových zdrojů

Než sáhnete po jakémkoli nástroji, musíte rozhodnout, jak se data ze zdroje budou vůbec získávat. Tomu se říká extraction type a je to rozhodnutí, které určuje čerstvost dat, spotřebu compute i složitost pipeline. Databricks rozlišuje tři základní vzory — full, inkrementální a streaming — plus specializovaný vzor change data capture (CDC).

Zdroj (2 mil. řádků) celá tabulka 2 000 000 řádků / běh FULL vše znovu bez change trackingu, malé objemy, periodický rebuild Zdroj + watermark updated_at > poslední běh ~2 000 změn / běh INKREMENTÁLNÍ jen nové/změněné vyžaduje spolehlivý change indikátor (timestamp, sekvence) + správu stavu Message bus Event Hubs, Kafka průběžně, event po eventu STREAMING sekundy–minuty nejnižší latence, ale always-on infrastruktura = vyšší cena Transakční log DB SQL Server, MySQL… INSERT / UPDATE / DELETE CDC změny + typ operace jediný vzor, který spolehlivě replikuje i mazání (delete)
Čtyři typy extrakce: full čte vždy vše, inkrementální jen změny od watermarku, streaming běží průběžně a CDC přenáší řádkové změny včetně typu operace.

Klíčový rozdíl mezi inkrementální extrakcí a CDC: inkrementální extrakce vidí jen „nový stav řádků", zatímco CDC zachovává typ operace — pozná tedy i mazání a změny klíčových sloupců. CDC ale vyžaduje sekvenční informaci (timestamp nebo pořadové číslo), aby šlo správně zpracovat eventy, které dorazí mimo pořadí.

Druhá část návrhu je konfigurace zdroje. U cloud storage (ADLS, S3, GCS) řídíte přístup přes Unity Catalog external locations (viz kapitola 3) a hodně záleží na struktuře složek: Hive-style partitioning (key=value) umožní automatickou extrakci partition hodnot a ploché adresáře s tisíci soubory zpomalují listing. U databází řešíte síť, secrets a dopad extrakce na zdrojový systém; u SaaS API zase rate limity, stránkování a OAuth; u message busů consumer groups a offset management.

PožadavekZvolte
Malý objem (< 100 tis. řádků), bez change trackinguFull extrakce
Velký objem, spolehlivý timestamp/sekvence, stačí hodinová/denní čerstvostInkrementální extrakce
Čerstvost v sekundách/minutách, zdroj publikuje eventyStreaming extrakce
Nutnost zachytit delete a typ operace, audit trailCDC extrakce
💡
Tip: Postupujte podle rámce z dokumentace: nejdřív požadavky (objem, latence, schopnosti zdroje, kvalita, síť, cena), pak mapování na extraction type, pak formát a nakonec validace návrhu. A rozhodnutí zdokumentujte — za rok se nikdo nedozví, proč jste nezvolili streaming, pokud to nikde nenapíšete.
⚠️
Pozor: Kdo čeká, že streaming je vždy „lepší", protože je rychlejší, plete si latenci s hodnotou. Pokud reporting potřebuje hodinovou čerstvost, always-on streaming infrastruktura jen pálí peníze — dokumentace v ukázkovém scénáři e-shopu volí právě hodinovou inkrementální dávku.
6.2

Volba ingesčního nástroje

Azure Databricks nabízí spektrum ingesčních nástrojů od plně spravovaných po plně vlastní kód. Na jednom konci stojí Lakeflow Connect s hotovými konektory, na druhém Spark Structured Streaming, kde si vše píšete sami. Mezi nimi leží Auto Loader pro soubory v cloud storage, COPY INTO pro SQL dávky a notebooky s JDBC/ODBC. Azure Data Factory hraje roli orchestrátoru a „přistávací dráhy" pro data z Azure ekosystému — ne transformačního enginu.

Lakeflow Connect má tři kategorie managed konektorů (podrobně v sekci 7.1): SaaS konektory (Salesforce, HubSpot, Jira, Workday…), které řeší autentizaci, inkrementální čtení, rate limity i schema evolution a běží na serverless compute; databázové konektory (CDC) (SQL Server, MySQL, PostgreSQL) postavené na čtení transakčního logu, které vyžadují ingestion gateway ve vaší síti a staging volume; a query-based konektory pro databáze bez CDC (Oracle, Teradata a další), které se plánovaně dotazují přes cursor column a gateway nepotřebují. Doplňkem jsou community konektory udržované komunitou. K tomu standard konektory pro cloud storage (interně Auto Loader) a message busy (Kafka, Pub/Sub, Pulsar), typicky používané v rámci Lakeflow Spark Declarative Pipelines. Seznam konektorů roste rychle — aktuální stav ověřte v dokumentaci.

NástrojTypický zdrojRežimMíra správyKdy sáhnout jinam
Lakeflow Connect (managed)SaaS aplikace, databáze (CDC)plánovaný i on-demandplně managedzdroj není podporován
Auto Loadersoubory v cloud storageinkrementální / streamingmanaged discovery, vlastní logikajednorázový load → COPY INTO
COPY INTOsoubory v cloud storageidempotentní batch (SQL)jednoduchá konfiguraceprůběžná ingesce ve velkém → Auto Loader
Structured StreamingKafka, Event Hubs, CDFstreamingplná kontrola = plná odpovědnoststačí-li deklarativní pipeline
Notebook + JDBC/ODBClibovolná DB s driverembatch, vlastní kódvše ručněexistuje-li managed konektor
Azure Data Factory / partner nástrojeAzure ekosystém, ETL platformyorchestrace + landingmimo Databrickstransformace patří do Databricks
Odkud data přicházejí? SaaS aplikace Relační databáze Soubory v cloud storage Message bus Lakeflow Connect managed SaaS konektor Potřebuji CDC (delete, mezistavy)? ano ne DB konektor (CDC) + ingestion gateway Query-based konektor cursor column, bez gateway nepodporovaná DB → JDBC Průběžná ingesce, nebo jednorázová dávka? průběžně dávka Auto Loader inkrementální discovery souborů COPY INTO idempotentní SQL Standard konektor / Structured Streaming deklarativní pipeline
Rozhodovací strom volby ingesčního nástroje podle typu datového zdroje. Obecné pravidlo: začněte nejvíce managed variantou, která splní požadavky.
CDC konektor vs. query-based konektor — kdy který?▼

Query-based konektory jsou lehčí alternativa CDC konektorů: místo čtení transakčního logu se dotazují přímo na zdrojovou tabulku přes cursor column (monotónně rostoucí timestamp nebo integer) a načítají řádky nad high-water markem z minulého běhu. Nepotřebují ingestion gateway ani staging storage a podporují mj. Oracle, Teradata, SQL Server, MySQL, PostgreSQL a zdroje Lakehouse Federation. Cílové tabulky umí vést jako SCD Type 1, SCD Type 2 nebo append-only.

Zvolte je, když CDC infrastruktura není dostupná, ale existuje spolehlivý cursor column. CDC konektor naopak potřebujete, když musíte zachytit každý mezistav řádku mezi běhy nebo spolehlivě sledovat delete. Daň za jednoduchost: query-based konektor zatěžuje zdrojovou tabulku přímými dotazy.

Auto Loader si drží stav zpracovaných souborů v checkpointu a nové soubory objevuje buď directory listingem, nebo přes file notification eventy — zvládá exactly-once zpracování i miliardy souborů a schema inference/evolution. COPY INTO je jeho dávkový sourozenec: idempotentní SQL příkaz, který si zpracované soubory eviduje v transakčním logu Delta tabulky, takže opakované spuštění data neduplikuje.

SQL
-- idempotentni davkovy load z landing zony
COPY INTO banka.bronze.transakce
FROM 'abfss://landing@datalake.dfs.core.windows.net/transakce/'
FILEFORMAT = PARQUET
COPY_OPTIONS ('mergeSchema' = 'true');
💡
Tip: Dokumentace: „Start with the most managed option that meets your requirements." K vlastnímu kódu (Structured Streaming, JDBC notebooky) sestupujte, až když managed vrstva vaše požadavky nesplní — každý řádek vlastního kódu je řádek, který budete udržovat.
⚠️
Pozor: ADF používejte na orchestraci a landing dat, ne na ETL transformace „přes" Databricks — transformační logika patří do Databricks. Pro on-premises databáze počítejte s ExpressRoute/VPN, nebo s ADF Self-Hosted Integration Runtime, který data nejdřív složí do cloud storage. Vedle ADF existují i partnerské ETL nástroje (přes Partner Connect, např. Fivetran) — nabídku ověřte v dokumentaci.
6.3

Volba formátu tabulky: Delta, Iceberg, Parquet

Nejdřív pojmy: file format (Parquet, CSV, JSON) určuje fyzické uložení dat na disku, table format (Delta Lake, Apache Iceberg) nad ním přidává metadatovou vrstvu — transakce, evidenci souborů a verzí schématu. Delta i Iceberg používají pod kapotou Parquet; liší se právě metadatovou vrstvou.

Parquet ukládá data sloupcově v row groups s min/max statistikami — odtud column pruning (čtou se jen potřebné sloupce) a predicate pushdown (přeskočí se row groups mimo rozsah filtru). Delta Lake k tomu přidává transakční log: ACID transakce, time travel, schema enforcement/evolution a jednotný batch + streaming přístup. V Azure Databricks je Delta výchozím formátem — když formát neuvedete, dostanete Delta tabulku.

Apache Iceberg volte primárně kvůli interoperabilitě: čtou a zapisují ho Snowflake, Trino, Athena, Flink a další. Unity Catalog umí spravovat managed Iceberg tabulky a fungovat jako Iceberg katalog pro externí enginy; cizí Iceberg tabulky (AWS Glue, Snowflake Horizon) lze připojit jako foreign tables. Existuje i UniForm — Delta tabulka, která si vedle sebe generuje Iceberg metadata, takže ji externí Iceberg klienti čtou bez kopírování dat; přesné schopnosti a limity ověřte v dokumentaci. Pozor na jednu asymetrii: liquid clustering a predictive optimization fungují pro Delta i managed Iceberg, ale Change Data Feed je specialita Delta Lake — stojí na jejím transakčním logu.

KritériumDelta LakeApache IcebergCSV/JSON
Výkon pro analytikuvýbornývýbornýslabý
ACID transakce / time travelanoanone
Integrace s Databricksnejhlubší (výchozí)podporovanázákladní
Interoperabilita napříč platformamiroste (+ UniForm)širokáuniverzální
Produkční doporučenívýchozí volbapři cross-platform požadavkujen landing zóna
✓
Shrnutí: Výchozí odpověď je Delta Lake. Iceberg nasaďte, když stejné tabulky musí číst a zapisovat enginy mimo Databricks. CSV/JSON konvertujte při ingesci do Delta — v landing zóně jsou v pořádku, jako trvalé analytické úložiště ne.
6.4

Partitioning

Partitioning rozděluje tabulku do segmentů podle hodnot sloupce; dotazy filtrované na partition klíč pak čtou jen relevantní část dat (partition pruning). Zní to jako univerzální dobro — ale dokumentace je nečekaně zdrženlivá: „Databricks recommends that you do not partition tables that contain less than a terabyte of data." Pod 1 TB režie správy partition metadat a riziko malých souborů převáží přínosy; nepartitionované Delta tabulky navíc automaticky těží z ingestion time clusteringu.

Pokud partitionujete, dodržujte dvě čísla: tabulka nad 1 TB a každá partition alespoň 1 GB dat. Dobrý partition klíč má nízkou kardinalitu (datum, region, kategorie), odpovídá nejčastějším filtrům dotazů a škáluje s růstem dat. Klíče jako customer_id nebo timestamp na sekundy vyrobí miliony mini-partitions a výkon zabijí.

SQL
-- partition podle data odvozeneho z timestampu (generated column)
CREATE TABLE banka.silver.transakce (
    transaction_id STRING,
    customer_id    STRING,
    amount         DECIMAL(12,2),
    transaction_ts TIMESTAMP,
    transaction_date DATE GENERATED ALWAYS AS (CAST(transaction_ts AS DATE))
)
PARTITIONED BY (transaction_date);

Trik s generated column stojí za zapamatování: Delta Lake pak umí odvodit partition filtry i z dotazů filtrujících na původní transaction_ts — analytici nemusí vědět, že tabulka je partitionovaná podle odvozeného data.

Časté chyby partitioningu▼
  • Over-partitioning: mnoho partitions s málo daty → problém malých souborů, pomalé listingy a dlouhé optimalizace. Příznak: pruning „funguje", ale dotazy jsou stále pomalé.
  • Vysoká kardinalita klíče: partitionování podle ID zákazníka či transakce nikdy nedopadne dobře — na to jsou clustering techniky (viz sekce 6.9).
  • Změna strategie = přepis tabulky: partition sloupce jsou součástí struktury tabulky; změna vyžaduje kompletní rewrite do nové lokace. Rozmyslete si klíč, než nalijete terabajty.
  • Nezdokumentované rozhodnutí: zapište klíč, očekávané velikosti partitions i dotazové vzory, které schéma zvýhodňuje.
ℹ️
Poznámka: Pro nové tabulky je dnes doporučenou alternativou liquid clustering — řeší přesně ty situace, kde partitioning selhává (vysoká kardinalita, nejisté dotazové vzory), a klíče lze měnit bez přepisu dat. Liquid clustering a partitioning se na jedné tabulce vylučují. Podrobně v sekci 6.9.
6.5

Volba typu SCD a implementace SCD Type 2

Atributy dimenzí (zákazník, produkt, pobočka) se v čase mění a slowly changing dimensions (SCD) definují, co s tím. Když se zákazník přestěhuje ze Seattlu do Portlandu, máte tři možnosti: hodnotu přepsat (a přijít o historii), zachovat starou verzi a založit novou, nebo sledovat jen předchozí hodnotu ve zvláštním sloupci.

KritériumType 0Type 1Type 2Type 3
Zachovaná historiejen původní hodnotažádnákompletníomezená (předchozí hodnota)
Dopad na storageminimálníminimálnívysokýstřední
Složitost dotazůjednoduchájednoduchávyššístřední
Typické užitíkonstanty, audit původní hodnotyopravy chyb, kontaktyatribuce prodejů, teritoriasrovnání před/po
Vazba z faktůnatural keynatural keysurrogate keynatural key

V praxi dimenze typy kombinují: datum registrace jako Type 0, e-mail a telefon jako Type 1, přiřazený region jako Type 2. Type 2 si šetřete na atributy, kde historická perspektiva ovlivňuje byznys rozhodnutí — verzovat kvůli změně telefonního čísla je zbytečná režie. Type 3 je nejméně častý; většinu scénářů, které po něm volají, lépe obslouží Type 2.

Změna ve zdroji (1. 3. 2024) C-555: Seattle → Portland MERGE SK cust_id city valid_from valid_to is_current 1001 C-555 Seattle 2020-01-15 2024-03-01 false 1002 C-555 Portland 2024-03-01 9999-12-31 true 1) UPDATE: uzavření platnosti staré verze 2) INSERT: nová verze s novým surrogate key (identity) SK 1001 · Seattle · platnost 2020-01-15 až 2024-03-01 SK 1002 · Portland · platnost od 2024-03-01 (aktuální) okamžik změny — intervaly na sebe navazují bez mezery 2020 9999-12-31 Fakta odkazují na konkrétní verzi přes surrogate key → historické prodeje zůstávají přiřazené Seattlu.
SCD Type 2: změna zákaznického atributu uzavře platnost staré verze řádku a vloží novou verzi; obě sdílí natural key, ale mají různé surrogate keys.

Implementace v Delta Lake: surrogate key vygeneruje GENERATED ALWAYS AS IDENTITY, platnost verzí drží sloupce valid_from/valid_to a příznak is_current:

SQL
CREATE TABLE banka.gold.dim_zakaznik (
    customer_sk   BIGINT GENERATED ALWAYS AS IDENTITY,
    customer_id   STRING NOT NULL,   -- natural / business key
    customer_name STRING,
    city          STRING,
    region        STRING,
    valid_from    TIMESTAMP NOT NULL,
    valid_to      TIMESTAMP NOT NULL,
    is_current    BOOLEAN
)
USING DELTA
TBLPROPERTIES ('delta.enableChangeDataFeed' = 'true');

Samotné zpracování změn je dvoufázové: MERGE nejdřív uzavře aktuální verze změněných záznamů a vloží úplně nové zákazníky, druhý krok pak vloží nové verze pro záznamy, jejichž stará verze byla právě uzavřena. Obě fáze přitom musí pracovat se stejným časovým okamžikem — jinak mezi valid_to staré a valid_from nové verze vznikne mikro-mezera a point-in-time dotaz do ní spadne. Čas si proto uložte do proměnné:

SQL
-- jeden casovy okamzik pro obe faze: intervaly pak navazuji bez mezery
DECLARE OR REPLACE VARIABLE zmena_ts TIMESTAMP DEFAULT current_timestamp();

-- krok 1: uzavri stare verze + vloz nove zakazniky
MERGE INTO banka.gold.dim_zakaznik AS t
USING banka.staging.zakaznici AS s
ON t.customer_id = s.customer_id AND t.is_current = true
WHEN MATCHED AND (t.city <> s.city OR t.region <> s.region
                  OR t.customer_name <> s.customer_name)
THEN UPDATE SET t.valid_to = zmena_ts, t.is_current = false
WHEN NOT MATCHED THEN INSERT
    (customer_id, customer_name, city, region, valid_from, valid_to, is_current)
VALUES (s.customer_id, s.customer_name, s.city, s.region,
        zmena_ts, CAST('9999-12-31' AS TIMESTAMP), true);

-- krok 2: vloz nove verze pro prave uzavrene zaznamy
-- EXISTS misto JOIN: jinak by zakaznik s N uzavrenymi verzemi dostal N kopii
INSERT INTO banka.gold.dim_zakaznik
    (customer_id, customer_name, city, region, valid_from, valid_to, is_current)
SELECT s.customer_id, s.customer_name, s.city, s.region,
       zmena_ts, CAST('9999-12-31' AS TIMESTAMP), true
FROM banka.staging.zakaznici s
WHERE EXISTS (SELECT 1 FROM banka.gold.dim_zakaznik h
              WHERE h.customer_id = s.customer_id AND h.valid_to = zmena_ts)
  AND NOT EXISTS (SELECT 1 FROM banka.gold.dim_zakaznik c
                  WHERE c.customer_id = s.customer_id AND c.is_current = true);

Dotaz na stav „k datu" pak filtruje interval platnosti — vrátí přesně jednu verzi na zákazníka:

SQL
-- stav dimenze k 15. 6. 2023 (point-in-time)
SELECT customer_id, customer_name, city
FROM banka.gold.dim_zakaznik
WHERE valid_from <= '2023-06-15 12:00:00'
  AND valid_to   >  '2023-06-15 12:00:00';
⚠️
Pozor: Dvě klasické pasti druhého kroku. První je fan-out: kdo místo EXISTS napíše JOIN na historické řádky (h.is_current = false), dostane pro zákazníka s N uzavřenými verzemi N kopií nové verze — a dimenze tiše nabobtná duplicitami. Druhá je volání current_timestamp() zvlášť v každém kroku: mezi valid_to staré a valid_from nové verze pak zbude mikro-mezera a point-in-time dotaz padnoucí přesně do ní nevrátí žádnou verzi. Obojí řeší jediná proměnná se sdíleným časem a EXISTS místo joinu.
💡
Tip: Ruční MERGE je skvělý na pochopení mechanismu, ale v produkci zvažte deklarativní pipeline s AUTO CDC API — SCD Type 2 tabulku udržuje automaticky včetně ošetření out-of-order záznamů (viz kapitola 7).
⚠️
Pozor: Kdo čeká, že SCD Type 2 nahradí Delta time travel, narazí na retenci: time travel má výchozí dostupnost 7 dní. Byznys historie patří do explicitních valid_from/valid_to sloupců; time travel je nástroj na provozní forenziku (viz sekce 6.6).
📚 Do hloubky na Learn: Compare SCD types · Apply mixed SCD strategies (EN)
6.6

Temporal (history) tabulky a Change Data Feed

SCD Type 2 sleduje byznysovou historii pro analytiku. Temporal (history) tabulky řeší něco jiného: technickou historii pro audit, debugging a reprodukovatelnost — „co přesně bylo v tabulce v úterý ve 14:30 a kdo to změnil". V Delta Lake se staví na dvou mechanismech: Change Data Feed (CDF) a time travel.

CDF po zapnutí zaznamenává každou řádkovou změnu s metadaty: _change_type (insert, update_preimage, update_postimage, delete), _commit_version a _commit_timestamp. Ve výchozím stavu je vypnutý a zachytává jen změny provedené po zapnutí — zapněte ho tedy dřív, než do tabulky nalijete produkční data.

SQL
-- zapnuti CDF na existujici tabulce
ALTER TABLE banka.silver.transakce
SET TBLPROPERTIES ('delta.enableChangeDataFeed' = 'true');

-- kdo, co a kdy zmenil v lednu (audit dotaz)
SELECT transaction_id, amount, _change_type, _commit_version, _commit_timestamp
FROM table_changes('banka.silver.transakce', '2026-01-01', '2026-01-31')
WHERE _change_type IN ('insert', 'update_postimage')
ORDER BY _commit_timestamp;

Time travel doplňuje CDF o dotazy na celý stav tabulky v minulosti — přes TIMESTAMP AS OF nebo VERSION AS OF; přehled operací dá DESCRIBE HISTORY. Dostupnost historie ale řídí retence: standardně se datové soubory drží 7 dní a log 30 dní. Pro compliance scénáře retenci prodlužte — obě vlastnosti nastavujte společně:

SQL
SELECT * FROM banka.silver.transakce TIMESTAMP AS OF '2026-01-15 14:30:00';
SELECT * FROM banka.silver.transakce VERSION AS OF 42;
DESCRIBE HISTORY banka.silver.transakce;

-- prodlouzeni retence pro audit (obe vlastnosti spolecne)
ALTER TABLE banka.silver.transakce SET TBLPROPERTIES (
    'delta.logRetentionDuration' = 'interval 90 days',
    'delta.deletedFileRetentionDuration' = 'interval 90 days');
Trvalý audit trail: perzistence CDF do history tabulky▼

Protože time travel i CDF podléhají retenci, dlouhodobý audit vyžaduje perzistenci změn do samostatné history tabulky. Elegantní vzor je Structured Streaming čtoucí change feed s trigger(availableNow=True) — spustí se po každém loadu, zpracuje vše nové jako dávku a skončí:

PYTHON
(spark.readStream
    .option("readChangeFeed", "true")   # delete prijdou jako _change_type = 'delete'
    .table("banka.silver.transakce")
    .writeStream
    .option("checkpointLocation", "/Volumes/banka/audit/checkpoints/transakce_history")
    .trigger(availableNow=True)
    .toTable("banka.audit.transakce_history"))

History tabulka pak obsahuje každou změnu za celý život dat — bez ohledu na retenční okno zdrojové tabulky.

ℹ️
Poznámka: Delší retence = vyšší náklady na storage (staré soubory nesmí smazat VACUUM). U regulovaných dat (FCA, ČNB) to je vědomý a zdokumentovaný obchod: platíte za storage, kupujete si prokazatelnost.
6.7

Granularita sloupců a tabulek

Granularita („grain") říká, co reprezentuje jeden řádek tabulky. Je to nejtěžší reverzibilní rozhodnutí v modelování: jednou agregovaná data už nikdy nerozagregujete. Pokud minutový agregát říká „průměrná teplota senzoru 75 °C", nikdy z něj nezjistíte, ve které milisekundě přišla špička.

Grain faktové tabulky určuje kombinace dimenzních klíčů: „jeden řádek na produkt, zákazníka, prodejnu a den". Přidáte-li hodinu, počet řádků násobíte. Dokumentace doporučuje grain explicitně deklarovat jako kontrakt („tato tabulka obsahuje jeden řádek na položku objednávky") dřív, než přidáte první sloupec. Volba je pak mezi atomic grain (nejjemnější detail ze zdroje — maximální flexibilita) a aggregate grain (předsumarizovaná data — rychlejší dotazy, omezené otázky). Časté řešení: držet obojí a agregáty udržovat jako materialized views nad atomickými daty.

U dimenzí granularita znamená způsob verzování: jeden řádek na zákazníka (Type 1), na verzi zákazníka (Type 2), nebo na zákazníka a období (periodické snapshoty). Grain dimenze musí sedět ke grainu faktů — transakce odkazující na verzi 5 zákazníka musí tu verzi v dimenzi najít.

Rozhodnutí ovlivňují čtyři síly: byznys otázky (nejdetailnější požadovaná analýza je dolní mez), dotazové vzory (příliš jemná data zdražují běžné agregace), náklady (jemnější grain = více řádků = více storage i compute; agregace senzorických dat na sekundy/minuty umí srazit počty řádků o 99 %) a compliance — finanční instituce často musí držet transakční detail bez ohledu na cenu.

💡
Tip: Když si nejste jistí, volte jemnější granularitu — agregáty dostavíte kdykoli později, ztracený detail už nikdy. Podmínkou je rozpočet na storage; proto tenhle argument vždy podložte odhadem objemů.
6.8

Managed vs. external (unmanaged) tabulky

U managed tables spravuje Unity Catalog metadata i datové soubory — data leží v managed storage lokaci schématu, katalogu nebo metastoru. U external tables spravuje Unity Catalog jen metadata; soubory leží v lokaci, kterou určíte klauzulí LOCATION nad registrovanou external location, a za jejich životní cyklus odpovídáte vy.

Kdo čeká, že „managed" znamená jen „Databricks mi vybral cestu", podceňuje, co všechno tím získává. Plná kontrola nad soubory umožňuje Unity Catalogu exkluzivní funkce: predictive optimization (automatická komprese a vacuum), automatic liquid clustering (výběr clustering klíčů podle dotazů), metadata caching a automatický úklid souborů po dropu. Smazaná managed tabulka jde vrátit příkazem UNDROP TABLE — výchozí okno je 7 dní a je konfigurovatelné v rozsahu 7–30 dní. Teprve po uplynutí tohoto okna Databricks datové soubory smaže, typicky do 48 hodin. Přesné hodnoty ověřte v dokumentaci.

CharakteristikaManaged tableExternal table
Datové soubory spravujeUnity Cataloguživatel
FormátyDelta Lake, Apache IcebergDelta, Parquet, CSV, JSON, Avro, ORC, text
Predictive optimizationanone
DROP TABLEUNDROP možný po výchozích 7 dní (7–30 konfigurovatelně), pak se soubory smažousoubory zůstávají ve storage
Typické užitívýchozí volba pro většinu tabuleksdílení souborů s externími systémy, migrace z Hive metastore, ne-Delta formáty

External tables mají legitimní use-cases: data musí přežít nezávisle na workspace, čtou/zapisují je nástroje mimo Databricks, migrujete z Hive metastore bez přesunu souborů, nebo potřebujete formáty mimo Delta/Iceberg. Počítejte ale s tím, že přímý přístup do storage obchází přístupová práva i audit Unity Catalogu — pro řízené sdílení je lepší Delta Sharing (viz sekce 5.6). A neregistrujte tutéž external tabulku ve více metastorech; změny se mezi nimi nepropagují.

✓
Shrnutí: Dokumentace: „Databricks recommends managed tables for most use cases." External tabulky nasazujte cíleně, zápisy pokud možno nechte jen přes Databricks a plánujte jejich konverzi na managed, jakmile původní důvod pomine.
6.9

Liquid clustering vs. partitioning vs. Z-ORDER

Všechny tři techniky stojí na stejném základu: data skipping. Delta Lake si pro každý soubor drží statistiky (min/max, počty nulls) a dotaz s filtrem přeskočí soubory, které hledané hodnoty obsahovat nemohou. Skipping ale funguje jen tehdy, když jsou související záznamy fyzicky pohromadě — a přesně to clustering techniky zařizují.

Liquid clustering je doporučený přístup pro nové tabulky (a v Public Preview i pro managed Iceberg tabulky — stav ověřte v dokumentaci). Na rozdíl od partitioningu umí změnit strategii bez přepisu dat: klíče definujete přes CLUSTER BY (až 4 sloupce), fyzickou organizaci provádí inkrementální OPTIMIZE, a když se dotazové vzory změní, prostě klíče přepnete přes ALTER TABLE.

SQL
-- faktova tabulka s liquid clusteringem (az 4 klice)
CREATE TABLE banka.gold.fakt_transakce (
    transaction_id STRING,
    customer_sk    BIGINT,
    branch_id      STRING,
    transaction_date DATE,
    amount         DECIMAL(12,2)
)
CLUSTER BY (transaction_date, customer_sk);

OPTIMIZE banka.gold.fakt_transakce;          -- inkrementalni clustering

-- zmena dotazovych vzoru? zadny prepis tabulky:
ALTER TABLE banka.gold.fakt_transakce CLUSTER BY (branch_id, transaction_date);
OPTIMIZE banka.gold.fakt_transakce FULL;     -- preusporadat i stara data

-- nebo vyber klicu nechat na platforme (vyzaduje predictive optimization)
-- CREATE TABLE potrebuje definici sloupcu nebo AS SELECT
CREATE TABLE banka.gold.objednavky (
    order_id     STRING,
    customer_sk  BIGINT,
    order_date   DATE,
    amount       DECIMAL(12,2)
)
CLUSTER BY AUTO;

-- automatiku lze zapnout i na existujici tabulce
ALTER TABLE banka.gold.objednavky CLUSTER BY AUTO;
PARTITIONING pevné adresáře podle hodnoty klíče date=2026-01-01/ date=2026-01-02/ malé soubory! date=2026-01-03/ • smysl až od ~1 TB, partition ≥ 1 GB • jen nízká kardinalita klíče • změna klíče = přepis celé tabulky • riziko over-partitioningu LIQUID CLUSTERING vyvážené soubory, související data pohromadě soubory ~cílové velikosti, data seskupená podle CLUSTER BY klíčů • změna klíčů bez přepisu (ALTER TABLE) • inkrementální OPTIMIZE, clustering-on-write • zvládá i vyšší kardinalitu, až 4 klíče • CLUSTER BY AUTO s predictive optimization Nové tabulky: liquid clustering. Partitioning jen pro velmi velké tabulky s jasným, stabilním klíčem. Nelze kombinovat!
Partitioning ukládá data do pevných adresářů podle hodnoty klíče; liquid clustering seskupuje související záznamy do vyvážených souborů a strategii lze měnit bez přepisu dat.

Z-ORDER je předchůdce liquid clusteringu: OPTIMIZE … ZORDER BY (…) kolokuje související data do stejných souborů, ale aplikuje se jen během OPTIMIZE, změna klíčů znamená plný přepis a nabízí jen transaction-level konkurenci (liquid clustering podporuje row-level). Potkáte ho u zděděných tabulek; migrace je přímočará — ALTER TABLE … CLUSTER BY (…) na nepartitionované tabulce a poté OPTIMIZE … FULL.

Deletion vectors — třetí kus skládačky▼

Bez deletion vectors znamená update/delete jediného řádku přepis celého Parquet souboru. S nimi Delta jen označí řádky za smazané v malém metadata souboru a čtení je aplikuje za běhu; fyzicky se soubory přepíší až při OPTIMIZE, auto-compaction nebo REORG TABLE … APPLY (PURGE). Vedlejší benefit: row-level concurrency — souběžné transakce mohou měnit různé řádky téže tabulky bez konfliktu. Pro nové tabulky jsou od Databricks Runtime 14.1 zapnuté ve výchozím stavu. Pozor pro compliance: „smazáno" neznamená „fyzicky pryč" — na to je potřeba REORG … APPLY (PURGE) + VACUUM.

💡
Tip: U tabulek s častými zápisy plánujte OPTIMIZE každou hodinu až dvě — nebo u managed tabulek zapněte predictive optimization a nechte to na platformě. CLUSTER BY AUTO pak posouvá automatiku ještě dál: platforma klíče sama vybírá i mění podle skutečných dotazů.
⚠️
Pozor: Liquid clustering nelze kombinovat s partitioningem na téže tabulce. U managed Iceberg tabulek v Unity Catalogu se dokonce klauzule PARTITIONED BY interpretuje jako liquid clustering klíče — žádné Hive-style partitions nevzniknou.
6.10

Lab 6: Design and Implement a Data Model in Unity Catalog (45 minut)

V roli data engineera retailové banky navrhnete a postavíte datový model v Unity Catalogu: zákaznickou dimenzi se SCD Type 2 historií, transakční faktovou tabulku s liquid clusteringem, audit trail pro FCA compliance nad Change Data Feed a inspekci i obnovu předchozích verzí tabulek přes Delta time travel.

▶ Otevřít lab na GitHubu (EN) · Learn modul k tématu — s krátkými výukovými videy

ℹ️
Poznámka: na kurzu lab prochází lektor jako demo. Postup je krokový a samoobslužný — pokud se na něj v rámci dne nedostane, projdete si ho samostatně.
✓
Sebekontrola: 1) Proč faktová tabulka odkazuje na SCD Type 2 dimenzi přes surrogate key, a ne přes customer_id? 2) Proč audit trail nestačí postavit jen na time travel a potřebujete Change Data Feed s perzistencí do history tabulky? 3) Kdy byste pro transakční fakta zvolili partitioning místo liquid clusteringu — a jaká dvě čísla přitom musí platit?