Archyno
Data modellingPraxe modelování

Od ER modelu k databázovému schématu

Normalizace má pověst akademické disciplíny, kterou si vysloužila tím, že se učí jako pět očíslovaných pravidel místo jediné opakované otázky: patří tenhle údaj sem?

11 min čteníER - crow's foot3 z 3

Krátká odpověď

  • Třetí normální forma v jedné větě: každý neklíčový sloupec závisí na klíči, celém klíči a ničem kromě klíče.
  • Náhradní klíč přežije, když si byznys rozmyslí, co vlastně něco identifikuje - a to si nakonec rozmyslí vždy.
  • Denormalizujte až po změření cesty čtení. Před měřením vyměňujete záruku správnosti za nepotvrzený přínos.
  • Převod z ER do SQL je mechanický: entita na tabulku, jeden k mnoha na cizí klíč na straně mnoha, mnoho k mnoha na vlastní tabulku.
Normalizované schéma objednávek ve čtyřech tabulkách. customers má klíč customer_id; orders má klíč order_id a cizí klíč customer_id; order_lines má klíč order_line_id s cizími klíči order_id a product_id plus quantity a unit_price; products má klíč product_id se sku, name a list_price.
Kam se tenhle článek dostane: čtyři tabulky, každý sloupec fakt o klíči své tabulky a každý vztah vynucený cizím klíčem, ne nadějí.

01Tabulka, kterou začíná každý#

Nenormalizovaná tabulka orders s order_id jako primárním klíčem a se sloupci customer_name, customer_email, product_names, quantities a total.
Jedna tabulka, pět problémů. Funguje bezchybně až do chvíle, kdy ji někdo použije podruhé.

Tohle není vymyšlený protivník - je to tvar, který má tabulkový list, a tabulkovým listem většina schémat začíná. Vyplatí se přesně pojmenovat, co je na něm špatně, protože "není normalizovaná" nevysvětluje nic:

To, co následuje, je modelování databázového schématu v úplně běžném smyslu: rozhodnout, jaké budou tabulky, který sloupec identifikuje řádek a kde smí fakt bydlet. Je to krok mezi ER diagramem a DDL, které databáze přijme, a vyplatí se udělat ho na papíře, protože každé z těchto rozhodnutí se draze vrací zpět, jakmile jsou v tabulce data.

  1. Nemůžete uložit zákazníka, který si nic neobjednal. Zákazník existuje jen jako sloupce na objednávce.
  2. Oprava e-mailu znamená aktualizovat každý řádek, na kterém zákazník vystupuje - a když jeden vynecháte, databáze drží dvě různé odpovědi.
  3. Smazání poslední objednávky smaže zákazníka. Informace zmizí jako vedlejší účinek něčeho, co s ní nesouvisí.
  4. product_names obsahuje seznam. Odteď každý dotaz, který potřebuje jeden produkt, parsuje řetězec a žádný index mu nepomůže.
  5. total může nesouhlasit s položkami, jejichž má být součtem.

Ta pětice má jména - vkládací, aktualizační a mazací anomálie, opakující se skupina a odvozená hodnota - a normalizace je prostě postup, který je odstraní.

02Nejdřív vyberte klíče#

Všechno další na tom závisí, takže to přichází dřív než tabulky. Primární klíč musí být jedinečný, nikdy null a nikdy se neměnit. Třetí podmínka je ta, která vyřadí většinu kandidátů.

PrvekNotaceCo znamená
Náhradní klíčbigint nebo uuidGenerovaný, bezvýznamný, navždy stabilní. Výchozí volba. Sekvenční celé číslo je kompaktní a přátelské k indexům; UUID umí vygenerovat klient a neprozrazuje objemy.
Přirozený klíčISBN, IBAN, kód zeměVýznamový, a bezpečný jen tehdy, když normalizační orgán garantuje, že se nezmění. Skutečně se kvalifikuje jen krátký seznam.
Složený klíčdva nebo více sloupcůSprávný pro spojovací tabulky, kde dvojice cizích klíčů je identitou a zároveň omezením jedinečnosti, které jste tak jako tak chtěli.
Byznysový klíččíslo objednávky, SKUUrčený lidem, musí být jedinečný a měl by být omezením UNIQUE, ne primárním klíčem - aby se dal opravit, když se v něm najde překlep.

03Normalizace ve třech krocích#

Normálních forem je šest a potřebujete tři. Každá je jediná otázka o tabulce a odpověď "ne" vám řekne, který sloupec kam přesunout.

PrvekNotaceCo znamená
První normální formažádné opakující se skupinyKaždý sloupec drží jednu hodnotu. Žádné seznamy oddělené čárkami, žádné product_1 / product_2 / product_3. Opakující se část rozdělte do vlastní tabulky.
Druhá normální formažádné částečné závislostiKaždý neklíčový sloupec závisí na celém klíči. Problém výhradně u složených klíčů: název produktu v tabulce (order_id, product_id) závisí na polovině klíče, takže patří do products.
Třetí normální formažádné tranzitivní závislostiŽádný neklíčový sloupec nezávisí na jiném neklíčovém sloupci. customer_email na objednávce závisí na zákazníkovi, ne na objednávce. Přesuňte ho do customers.

Staré shrnutí je pořád nejlepší: každý neklíčový sloupec závisí na klíči, celém klíči a ničem kromě klíče.

Proveďte přes ně plochou tabulku. 1NF rozdělí product_names a quantities do tabulky order_lines, jeden řádek na produkt. 2NF si všimne, že název a cena produktu závisí jen na produktu, takže se objeví products. 3NF si všimne, že jméno a e-mail zákazníka závisí na zákazníkovi, ne na objednávce, takže se objeví customers. Čtyři tabulky, což je právě titulní diagram - a žádný krok nevyžadoval úsudek, jen tu otázku.

04Odvozené hodnoty a denormalizace#

Sloupec total v ploché tabulce je jiný problém než ostatní čtyři: není špatně umístěný, je nadbytečný. Dá se spočítat z položek objednávky, takže s nimi může nesouhlasit - a jednou nesouhlasit bude.

Tři legitimní odpovědi v pořadí podle preference: počítat ho v dotazu; počítat ho v pohledu; uložit ho a nechat databázi, ať ho udržuje - generovaný sloupec, materializovaný pohled nebo trigger. Legitimní není uložit ho a spoléhat, že si aplikační kód vzpomene ho aktualizovat; to je verze, která produkuje faktury, které nesedí.

Sáhněte po něm, když

  • Změřený vzorec čtení je příliš pomalý a spojení je prokazatelně příčinou
  • Hodnota je snímkem v čase, ne odvozením - cena v okamžiku objednání
  • Reportovací tabulka plněná naplánovanou úlohou, jasně takto pojmenovaná
  • Databáze si kopii umí udržovat sama, takže se nemůže rozejít

Sáhněte po něčem jiném, když

  • Mohlo by to být pomalé později - nejdřív měřte, obvykle to pomalé není
  • Aplikační kód si musí pamatovat, že kopii má držet v souladu
  • Duplikát je zároveň zdrojem pravdy pro něco jiného
  • Denormalizujete transakční schéma kvůli obsluze dashboardu

05Modelování dědičnosti#

ER model umí vyjádřit nadtyp s podtypy; relační databáze takovou konstrukci nemá, takže fyzický model musí vybrat jedno ze tří rozložení. Všechna tři se široce používají a volba je skutečným kompromisem.

PrvekNotaceCo znamená
Jedna tabulkajedna tabulka, sloupec typuSloupce všech podtypů v jedné tabulce, většina z nich null. Jednoduché dotazy, žádná spojení - a databáze neumí vynutit "platba šekem musí mít kód banky".
Tabulka na podtyptabulka pro každý, sdílený klíčRodičovská tabulka se společnými sloupci a dceřiná tabulka na podtyp, navázaná na ni klíčem. Omezení fungují pořádně; každý dotaz se spojuje.
Tabulka na konkrétní typzcela oddělené tabulkyŽádná sdílená tabulka. Rychlé a čisté v rámci podtypu - a dotaz na "všechny platby" znamená unii, která roste s každým přidaným podtypem.

Hrubé pravidlo: málo podtypů s převážně společnými sloupci mluví pro jednu tabulku; hodně podtypů s rozcházejícími se sloupci a reálnými omezeními mluví pro tabulku na podtyp; a podtypy, na které se nikdy nedotazujete společně, mluví pro oddělené tabulky. Diagram tříd pro tutéž doménu si dědičnost obvykle vybral, aniž by cokoli z tohohle řešil, a právě proto tyhle dva modely tady smějí být odlišné.

06Cesta k DDL#

Logický ER model se na DDL mapuje téměř mechanicky, což je odměna za to, že jste ho nakreslili pořádně:

PrvekNotaceCo znamená
EntitaCREATE TABLEJedna tabulka. Název tabulky v množném čísle, název entity v jednotném - vyberte si jedno a držte se toho.
Primární klíčPRIMARY KEYImplikuje not null a unique a vytváří index.
VztahREFERENCESCizí klíč na straně mnoha. Index si přidejte sami - většina databází ho pro cizí klíč nevytvoří a jeho absence zpomalí mazání na plazení.
Povinný konecNOT NULLVnitřní čárka ve vraní noze je přesně tohle omezení.
Jeden k jednomuUNIQUE na cizím klíčiJinak je to vztah jeden k mnoha, který má zatím jen jeden řádek.
Spojovací entitasložený PRIMARY KEYOba cizí klíče dohromady. Právě to zabrání tomu, aby se tatáž dvojice zapsala dvakrát.

Dvě věci, které vám diagram neřekne a DDL o nich musí rozhodnout: co se stane při mazání (CASCADE u identifikujícího vztahu, RESTRICT téměř všude jinde) a které sloupce dostanou indexy nad rámec klíčů. Obojí jsou rozhodnutí o chování a zátěži, ne o modelu, a obojí se vyplatí zapsat vedle schématu, ne je objevit později v logu pomalých dotazů.

07Časté chyby#

  1. Normalizování za hranici užitečnosti. 3NF je cíl transakčního schématu. Rozdělit tabulku proto, že se sloupec možná jednou zopakuje, nepřinese nic a bude stát spojení navždy.
  2. Žádné cizí klíče, "kvůli výkonu". Cena je jedno vyhledání v indexu při zápisu; přínosem je, že osiřelé řádky jsou nemožné. Skoro nikdy to není výměna, která se vyplatí.
  3. Nullovatelné sloupce zastupující chybějící tabulku. Šest sloupců, které jsou vyplněné jen pro jeden druh řádku, je podtyp, který si říká o vlastní tabulku.
  4. status jako volný text. Omezte ho - kontrolním omezením, enumem nebo číselníkovou tabulkou - jinak bude do roka obsahovat shipped, Shipped i SHIPPED.
  5. Časová razítka bez časové zóny. Správně přesně jednou, v jedné kanceláři, do prvního přesunu serveru.
  6. Diagram opuštěný po první migraci. Diagram schématu, který nesouhlasí s databází, je horší než žádný, protože mu lidé věří.

Pokud symboly kardinality na diagramech výše potřebují překlad, jsou pokryté v notaci vraní nohy; tvar samotného modelu je v ER diagramech.

Po jednom řádku na každé

  1. 01Klíče vyberte dřív než tabulky; jedinečné, not null a nikdy se neměnící.
  2. 02Každý neklíčový sloupec závisí na klíči, celém klíči a ničem kromě klíče.
  3. 031NF rozdělí opakující se skupiny, 2NF opraví částečné klíče, 3NF přesune špatně umístěné fakty.
  4. 04Denormalizujte na základě měření a jen tam, kde kopii udržuje databáze.
  5. 05Historická cena není duplikát - je to jiný fakt.
  6. 06Vraní noha se na DDL mapuje téměř mechanicky; indexujte si cizí klíče.

08Časté dotazy#

Co je třetí normální forma?

Tabulka je ve třetí normální formě, když každý neklíčový sloupec závisí na klíči, celém klíči a ničem kromě klíče. V praxi: žádné opakující se skupiny, žádný sloupec závislý jen na části složeného klíče a žádný sloupec závislý na jiném neklíčovém sloupci.

Jaký je rozdíl mezi náhradním a přirozeným klíčem?

Přirozený klíč jsou data, která řádek už identifikují, například ISBN. Náhradní klíč je bezvýznamná generovaná hodnota, například celé číslo nebo UUID. Náhradní klíče zůstanou stabilní, když si byznys rozmyslí, co vlastně něco identifikuje - a to si nakonec rozmyslí vždy.

Kdy je denormalizace opodstatněná?

Když jste změřili cestu čtení, kterou normalizace zpomalila příliš, a umíte žít s tím, že zduplikovaná hodnota zestárne. Denormalizovat dřív, než tu míru máte, znamená vyměnit záruku správnosti za výkonnostní přínos, o kterém jste si nepotvrdili, že existuje.

Jak se v relačním schématu implementuje dědičnost?

Tři možnosti: jedna tabulka pro celou hierarchii s rozlišovacím sloupcem a spoustou nullovatelných sloupců, jedna tabulka na konkrétní třídu se zopakovanými společnými sloupci, nebo jedna tabulka na třídu spojená přes sdílený klíč. Která je správná, závisí na tom, jak často se dotazujete napříč hierarchií, oproti tomu, jak moc se podtřídy liší.

Jak udělat z ER diagramu SQL?

Každá entita se stane tabulkou, každý atribut sloupcem a identifikující atribut primárním klíčem. Vztahy jeden k mnoha se stanou cizím klíčem na straně mnoha a vztahy mnoho k mnoha vlastní tabulkou. Pak přidejte omezení not null a unique, která kardinality na diagramu naznačují.

V této sérii
  1. 01ER diagramy
  2. 02Notace vraní nohy
  3. 03Návrh schématu

Související články

Všechny články