Návrh relační databáze

Návrh relační databáze
« kdy: 25. 04. 2019, 13:18:45 »
Nechci někomu na potkání vykládat know-how, ani nežádám vyzrazení suprfičur ostatních. Spíš chci dát prostor ostříleným architektům, aby se pochlubili svým originálním přístupem a inspirovali jiné ztracené duše.
Nastíním problém, který jsem řešil u nás a zároveň předložím řešení, které momentálně používáme:

Vyvíjíme nástroj pro vytváření formulářových aplikací. Je psaná ve WPF, datovou část stavíme nad MSSQL. Klíčem je pro nás silně relační databáze. Výhodou je následná vizualizace její struktury v návrháři datových zdrojů (přes cizí klíče je možné se "proklikat" hlouběji a vynášet sloupce, které jsou potřeba).
Pomocí tohoto nástroje, který obsahuje rozšířené formulářové kontrolky a další komponenty, se poskládá celá appka podle potřeb zákazníka. Její skládání mají na starost implementátoři.

Momentálně vytváříme aplikaci pro evidenci blíže nespecifikovaných objektů, pro účely dalšího popisu řekněme auta a jejich součásti. Objekty jsou mezi sebou svázány (kolo je namontované na nějaké auto). Nad objekty jsou vytvářené různé agendy (např. tickety, platnost kontrol, ...).
Problém je, že objektů je spousta druhů, každý druh má své specifické vlastnosti, které jsou irelevantní pro jiné druhy (auto má počet náprav, které jsou pro kola nesmyslnou vlastností, a naopak poloměr je pro kolo fajn, ale evidovat ho u auta je jaksi zbytečné).
Rozhodli jsme se proto, že objekty budeme dělit do skupin a pro každou skupinu bude vytvořena konkrétní tabulka s potřebnými sloupci. S tím samozřejmě přišla spousta problémů, například jednoznačný identifikátor, který by byl snadný k vygenerování a přesto dostatečně rychlý při vyhledávání (GUID je z hlediska rychlosti tragický). Nebo způsob, jak propojit přes cizí klíče tyto tabulky s tabulkami jednotlivých agend. V neposlední řadě je tu samotné zobrazení dat v aplikaci - jak v seznamu ticketů vypsat jméno objektu, když je pokaždé uložené v jiné tabulce?
Po řadě pokusů a omylů jsme dospěli k řešení, které jistě není dokonalé, ale momentálně splňuje naše požadavky. Pomocí řady triggerů, funkcí, procedur a jiných hrůz jsme zapracovali do struktury databáze tabulku, která funguje jako most mezi tabulkami objektů a tabulkami agend. Toto přemostění obsahuje primární autoinkrementální klíč, který je používaný jako cizí klíč v tabulkách agend a zároveň jako cizí klíč u jednotlivých řádků v tabulkách objektů. Pod každou objektovou tabulkou je vygenerovaný AFTER INSERT, DELETE trigger, který po insertu řádku objektové tabulky vytvoří nový řádek v tabulce přemostění a Id vytvořeného řádku následně vloží do řádku s objektem, který trigger spustil. Toto Id je používáno ve všech místech aplikace - agendy, hierarchie objeků, atd. Obdobná automatika funguje při mazání.
Další tabulka slouží k evidenci skupin (její název, název tabulky). Pod touto tabulkou je trigger, který má na starost generování view, které dává k dispozici přehled všech evidovaných objektů a jejich základních vlastností (evidenční číslo, název, ...). Při vytvoření nové skupiny je select view triggerem upravený tak, aby prováděl union i z tabulky nové skupiny. Implementátor pak ví, že přehled objektů je v tomto view a při vytváření datového zdroje formulářů agend chodí pro vlastnosti objektů právě sem (je to prakticky jediná situace, kdy nemůže při vytváření datového zdroje jednoduše procházet vazby mezi tabulkami).
Tímhle molochem je zajištěná integrita dat (nelze smazat objekt, na který je vystaven ticket apod), každý objekt má svůj jednoznačný identifikátor, a zároveň není v databázi hypertabulka, která by musela obsahovat stovky sloupců, aby zahrnula všechny evidovatelné vlastnosti.

Popsaný přístup má samozřejmě i své nevýhody. Mezi největší momentálně řadím nemožnost/náročnost přesunu objektu z jedné skupiny do druhé.

Řešili jste někdy něco podobného? A jak?


Re:Návrh relační databáze
« Odpověď #1 kdy: 25. 04. 2019, 14:15:07 »
Já bych váš text parafrázoval jako „nejprve jsme se rozhodli pro silně relační databázi, ale pak jsme otočili a z databáze jsme udělali jen nestrukturované úložiště“. Možné jsou oba přístupy, každý má své výhody a nevýhody. Pokud chcete ukládat nestrukturovaná data, jsou na to obvykle lepší NoSQL databáze. Pokud byste chtěli „silně relační databázi“, znamená to zapomenout na nějaké skupiny objektů a univerzální tabulky, ale prostě v databázi opravdu namodelovat to, co chcete řešit. Takže když máte auta a kola, budete mít tabulku aut a tabulku kol, přičemž v tabulce kol bude odkaz do tabulky aut. Ano, znamená to vytvořit velké množství tabulek, ale tohle je model, kdy hodně využíváte vlastností relačního databázového modelu.

Logik

  • *****
  • 854
    • Zobrazit profil
    • E-mail
Re:Návrh relační databáze
« Odpověď #2 kdy: 25. 04. 2019, 14:22:46 »
Já bych v takovémto případě velmi silně přemýšlel nad kombinací SQL a noSQL přístupu. Tedy objekty všechny v jedné tabulce, a ty variabilní vlastnosti uložené jako json.

Nevím, jak přesně umí MSSQL s json, ale v postgresql se s tím krásně pracuje, včetně indexace.

Jediné, co mne teď napadá, že to z běžných věcí neumí, jsou cizí klíče (na položky jsonu), ale to jde v případě potřeby dopsat trigerama.

Re:Návrh relační databáze
« Odpověď #3 kdy: 25. 04. 2019, 14:29:48 »
Filip Jirsák: Tenhle postup by se mi taky líbil, problém je v tom, že Monitor má cizí klíč ParentId, což může být Počítač z tabulky Pocitace, ale také DVD přehrávač z tabulky dbo.ElektronickaZarizeni. Je to ten samý atribut, ale pokaždé směřuje jinam.
Nevím, jestli jsme se náhodou špatně nepochopili, ale nevidím nic nerelačního na tom, když všechny tabulky se skupinami objektů mají cizí klíč MostId do tabulky dbo.Most, a všechny agendy se odkazují cizím klíčem MostId do téže tabulky.

Logik: Snažit se držet vazbu triggery je dle mého cesta do pekel.

Re:Návrh relační databáze
« Odpověď #4 kdy: 25. 04. 2019, 14:36:51 »
Řešili, několikrát. Používáme tyto tři šablony:

1. Item Extension Codes

A. Máme tabulku položek, kde jsou její základní údaje (branch plant, item number, item description, item type, gl class atd.)
B. A pak máme tabulku "Item Extension Codes", která má PK stejný jako ta první. V té máme cca 120 sloupců pojmenovaných stylem "number01, number02, date01, date02, text01,..."
C. Další tabulka je tabulka IID. Má sloupce Branch Plant, IID Key, IID Value a IID Description. Typický záznam je Branch Plant 728 (Brno), IID Key VPRODTYPE, IID Value "S2", IID Description "NHP SAS 2.5 10K"
D. A nakonec existuje tabulka "Extension Code Definition", kde je primárním klíčem Branch Plant, Item Type a FieldName. Další sloupec je Description, příznak Mandatory a IID Key. Do té se při nastavování databáze třebas napíše, že pro Branch Plant 728 (Brno) a Item Type IM (vyráběná položka) se sloupec "text05" jmenuje "Vendor Product Type", Mandatory má nastaveno na "yes" a IID klíč je "VPRODTYPE".

Celé to pak funguje tak, že založím položku v první tabulce. Do té druhé můžu ale nemusím. Pro tu druhou funguje formulář tak, že je tam tuším na třech záložkách až stovky políček. Systém sám podle tabulky z bodu D ví, které zobrazit (mají mandatory yes nebo no) a které ne (nemají záznam nebo mají mandatory disabled). Z tabulky D pak i nastaví správný popisek daného pole. Takže pro každý typ položky (nakupovaná, vyráběná, polotovar, fiktivní atd.) se zobrazí jen ta pole, která sleduji. Tabulka C se pak používá na kontrolu zadaných hodnot - pokud tabulka D specifikuje nějaký klíč, tak se zaprvé uživateli nabízí seznam hodnot a zadruhé se ověřuje, že vybral některou z nich.

Přidat nový atribut je pak o tom najít si pro danou pobočku a typ položky dosud nepoužité pole a udělat pro něj záznam do tabulky D.

2. Item Cross References

A. Máme tabulku položek, kde jsou její základní údaje (branch plant, item number, item description, item type, gl class atd.)
B. Mámě tabulku Item Cross Reference Type. Primární klíč je XType. Jediný další je sloupeček Description. Hodnoty typu VP = Vendor Part Number, EM = Customer Model Number atd.
C. A finálně tabulka Item Cross Reference, kde primární klíč je Item Number, Address Number a XType.

Do tabulky A se vkládají položky. Ke každé je pak možné do tabulky C přiřadit další údaje. Tím, že je v tabulce C v primárním klíči i Address Number, tak můžete mít jeden údaj (například Customer Part Number) pro různé address booky jiný. Address Book je typicky ID zákazníka, ID dodavatele, ID nákupčího apod. Takže když někomu dodáte svou položku 3731052, tak mu můžete na dodací list napsat číslo, jaké chce on. Což je docela běžné, že stálí zákazníci chtějí objednávat podle jejich čísla položky. A pokud jednu položku dodáváte více zákazníkům, tak se vám tahle vlastnost tabulky C dost hodí.

3. Kaskáda tabulek

A. Máme základní tabulku, například Transaction. Primární klíč ID transakce. Další sloupce typu datum transakce, účetní datum, typ transakce, celková částka atd.
B. K ní máme další tabulku, například InventoryTransaction. Primární klíč je stále to samé ID transakce a má FK na tabulku Transaction. Přidává další sloupce typu Item Number, Quantity, Unit of Measure, Branch Plant atd.
C. A máme i jinou tabulku, například PaymentTransaction. Primární klíč stále to samé ID transakce a opět FK na Transaction. Přidává sloupce typu VAT Code, Net Amount, atd.
D. A ještě jiná tabulka pro EventTransaction. Klíč stále stejný a opět FK na Transaction. Navíc sloupce jako EventId, EntryType, AuthorizationMethod atd.

Každá transakce je pak v tabulce A s tím, že dodatečné údaje má v některé z dalších tabulek podle typu transakce. Tohle se používá ve chvíli, kdy mám několik typů daného objektu, které ale znám už ve fázi návrhu. Výhoda je v tom, že všechny sloupce můžete hezky navázat přes foreign key a obecně se s tím dělá trochu lépe.

--- Co vybrat ---

Metoda 1 je docela snadná na implementaci a dělá se k ní i hezké uživatelské rozhraní. Dobře se pro to píší sestavy. Blbě se s tím ale dělá cokoliv obecného. Do té míry, že vám sestava pro Brno nebude fungovat v Ploveru, protože tam mají stejný údaj v jiném sloupci, protože ten původní už roky používali pro jiného zákazníka.

Metoda 2 má výhodu v tom, že k jedné položce nejen že máte libovolný počet dodatečných údajů, ale dokonce pro každého zákazníka/dodavatele jinou hodnotu. Hůř se proto ale dělá uživatelské rozhraní - zaprvé nevíte který z definovaných 84 typů Cross Reference máte nabídnout, zadruhé z toho hezké okénko neuděláte už proto, že dopředu nevíte pro kolik různých zákazníků uživatel bude chtít vyplnit End Customer Model Number.

Metoda 3 je velmi jednoduchá na implementaci. Vše je předem dáno a vy si můžete snadno vytvářet formuláře, sestavy, integritní omezení apod. Nevýhoda je v tom, že za běhu už nic nezměníte. A skrytá nevýhoda je v tom, že se vám v průběhu let začnou vývojáři v té kaskádě tabulek ztrácet a budou mít tendenci to lepit novými tabulkami.

Všechny mají výhodu v tom, že máte jednu tabulku A, kde máte definované všechny položky/transakce apod. Základ formuláře nebo sestavy tedy má jediný zdroj, jedinou tabulku. Stejně tak tabulky typu kusovník se budou odkazovat přes FK právě do tabulky A. Jediné, co si pak musíte dolepit jinak, jsou dodatečné informace.
« Poslední změna: 25. 04. 2019, 14:42:19 od KarelE »


Re:Návrh relační databáze
« Odpověď #5 kdy: 25. 04. 2019, 14:46:13 »
Filip Jirsák: Tenhle postup by se mi taky líbil, problém je v tom, že Monitor má cizí klíč ParentId, což může být Počítač z tabulky Pocitace, ale také DVD přehrávač z tabulky dbo.ElektronickaZarizeni. Je to ten samý atribut, ale pokaždé směřuje jinam.
Nevím, jestli jsme se náhodou špatně nepochopili, ale nevidím nic nerelačního na tom, když všechny tabulky se skupinami objektů mají cizí klíč MostId do tabulky dbo.Most, a všechny agendy se odkazují cizím klíčem MostId do téže tabulky.
V relačních databázích to není ten samý atribut, byly by to dva různé atributy ParentPočítačId a ParentElektronickazarizeniId. Plus kontrola, že vyplněn je právě jeden.

Pokud ty typy, na které se odkazujete, tvoří strom (např. počítač a DVD mají společného předka, na kterého by mohl odkazovat Monitor.ParentId), dalo by se to v PostgreSQL řešit pomocí dědičnosti tabulek.

Záleží hlavně na tom, kolik tam takových vazeb máte. Pokud monitor může odkazovat na dva tři různé typy, můžete použít ty různé sloupce. Pokud množství vazeb je spíš „každý s každým“, není relační model asi ten nejvhodnější a zvážil bych grafovou databázi.

Kit

  • *****
  • 568
    • Zobrazit profil
    • E-mail
Re:Návrh relační databáze
« Odpověď #6 kdy: 25. 04. 2019, 14:48:55 »
Záleží na tom, co od toho chcete. Dá se to pojmout třeba i tak, že jedno auto == jeden záznam v MongoDB. Všechny jeho komponenty budou nacpány do jednoho JSONu jako dokument. Pro některé UC to může být naprosto vyhovující, pro jiné nikoli.

Logik

  • *****
  • 854
    • Zobrazit profil
    • E-mail
Re:Návrh relační databáze
« Odpověď #7 kdy: 25. 04. 2019, 15:09:19 »
Urvustop: Pokud jde o konkrétní implementaci jednoho cizího klíče do JSONu, kde je problém? V čem je to cesta do pekel? Ten trigger bude mít naprosto jasnou sémantiku, je to obecné, bez problémů rozšiřitelné řešení, pro další vývoj naprosto transparentní (nijak se nelišící od "nativních" FK). Kde je ta cesta do pekel?

===

Fór je v tom, že tato situace nemá dobré řešení. Něco musíš oželit. A furt radši jednou napíšu vlastní implementaci foreign key, abych pak s databází pracoval naprosto standardně, než používal antipatterny typu EAV, nebo ukládání vlastností do políček number01, number02, number03, ani se ti databáze nerozpadá na padesát milionů tabulek, kde řešíš klasické problémy s mnohonásobnými dědičnostmi.

Řešení s JSON a explicitně napsaným triggerem neporušuje žádné databázové paradigma. Řeší problém "řídkých dat" pomocí nástroje na ukládání řídkých dat - a jen si dopíšeš jednu operaci, kterou (zatím) současná verze postgresu neumí.

Jiné zde navržené postupy zpravidla ohýbají relační databáze a práce s takovým systémem bude dřív či později na palici. Protože se snaží nacpat řídké struktury do

plných matic, což prostě rozumným způsobem nejde a ať se to "vobčůrá" jakkoli, tak to bude vždycky jen "vobčůraný". Ať uděláš s kladivem cokoli, na šroubování to bude pořád hodně nešikovnej nástroj.

Filip, Kit:
Grafové a jiné nosql databáze jsou sice dobré, ale do té doby, než s nima chce člověk pracovat v součinnosti s věcma, které má v SQL databázi. Např. proto se prosazují "in-databaze" fulltexty, protože fulltext mimo databázi může být nakrásně rychlejší, lepší a nevím co, ale když chceš kromě fulltextu filtrovat ještě podle dalších X kritérií, tak je to na palici. Navíc rozdělení dat do dvou databází musíš řešit takové lahůdky, jako synchronizace transakcí atd. atd....
A protože se na většinu věcí SQL hodí hodně dobře, zpravidla je lepší cesta používat nosql rozšíření SQL databází - např. ten json sloupec - než data dělit do dvou různých databází, anebo se zcela zbavovat možností SQL (a ukládat vše do noSQL databáze).


Re:Návrh relační databáze
« Odpověď #8 kdy: 25. 04. 2019, 15:26:32 »
KarelE:
Díky za skvělý popis. U všech tří metod mě napadá otázka: Jak ošetřujete zabalení ukládání změn do transakce? Pokud máte například u první metody formulář rozdělený na záložky, musí uživatel provádět ukládání na každé zvlášť, nebo volání tří updatů (pro každou záložku) provedete transakcí?
V prvních verzích jsme měli také nespecifikované univerzální sloupce, ovšem naráželi jsme na dva zásadní problémy. Prvním bylo zpřístupnění dat za účelem integrace ve formě pochopitelné pro druhou stranu. Vytvoření pohledu z tabulky, kdy pro různé řádky představuje jeden sloupec různé atributy, bylo značně komplikované, a výsledek byl navíc statický a musel se upravovat při vytváření dalších typů objektů.
Druhým problémem byl přesun objektu z jednoho typu do druhého - sloupec v tu chvíli znamenal něco jiného, opět to končilo specifickou jednorázovou operací, jejíž vytvoření zabíralo zbytečný čas.

V relačních databázích to není ten samý atribut, byly by to dva různé atributy ParentPočítačId a ParentElektronickazarizeniId. Plus kontrola, že vyplněn je právě jeden.
Takový přístup podle mě není správný. N-sloupci vyjadřujete jednu vlastnost, nehledě na to, že musíte provádět další ošetření. Opět nevidím nic špatného na tom, že sloupec ParentId odkazuje do tabulky, která obsahuje řekněme core objektů, a tabulky skupin obsahují jejich vlastnosti.

Aplikace je tvořena s důrazem na co největší univerzálnost a obecnost (bohužel). Tedy například parent objektu může být jakýkoliv jiný objekt (pochopitelně jen jeden).

A co jsem měl zmínit nejspíš hned na začátku: Použité technologie (MSSQL+C#) jsou kvůli oblasti trhu, ve které působíme, nedotknutelné.

Re:Návrh relační databáze
« Odpověď #9 kdy: 25. 04. 2019, 15:55:16 »
Filip Jirsák: Tenhle postup by se mi taky líbil, problém je v tom, že Monitor má cizí klíč ParentId, což může být Počítač z tabulky Pocitace, ale také DVD přehrávač z tabulky dbo.ElektronickaZarizeni. Je to ten samý atribut, ale pokaždé směřuje jinam.
Nevím, jestli jsme se náhodou špatně nepochopili, ale nevidím nic nerelačního na tom, když všechny tabulky se skupinami objektů mají cizí klíč MostId do tabulky dbo.Most, a všechny agendy se odkazují cizím klíčem MostId do téže tabulky.

Logik: Snažit se držet vazbu triggery je dle mého cesta do pekel.

Nevím jestli jsem pochopil celé téma diskuze, nicméně podotýkám, že v některých ORM existuje Polymorphic associations (ActiveJDBC, Hibernate). Např. Image má parent_id a parent_type, takže lze přiřadit k různým typům záznamu (třeba Section i Article) - typ se zjistí z parent_type. Databázově to sice tak čisté ale občas to může být vhodné řešení.


Re:Návrh relační databáze
« Odpověď #10 kdy: 25. 04. 2019, 16:33:47 »
Používáme už skoro 20 let defakto ORM uložení do SQL - objekty a vazby mezi nimi.

Tabulka objektů se základními parametry objektů (ID objektu, ID typu objektu, název, datum vytvoření, přístupová práva atd.). ID typu objektu odpovídá příslušné třídě v javě - potomku InfoObject. Přímo třída objektu může nést už byznys kód, protože jsou vytvořené pro konkrétní účel (téma, dokument, uživatel, firma, skupina, obrázek, žádost, atd. atd.).

Pak je evidenční tabulka atributů, která obsahuje typ (string/int/date/JSON) a ID typu atributu. Stále častěji používáme typ JSONAttrib. Opět typu atributu odpovídají třídy v javě.

Každý atribut má vlastní tabulku attr_IDatributu se sloupcem value dle jeho typu a samozřejmě id_obj s navázáním na objekt.

Tabulka relations s ID typu vazby, id_obj_from, id_obj_to + pár dalších údajů. ID vazby odpovídá příslušné třídě v javě - potomku Relation. Přímo třída vazby může nést už byznys kód, protože je pro konkrétní účel a obvykle si i kontroluje, zda se ji snažíme vázat na správný typ objektu.

Je nad tím poměrně robustní vrstva v javě, která vše přes weak vazby kešuje v paměti. Paměť je dnes velice levná. DB slouží pro perzistenci a pro vyhledávání.

Tabulka 4 mil. objektů cca 100 typů,  1000 tabulek atributů, tabulka 20 mil. vazeb cca 150 typů. Vše provázané cizími klíči přes objID včetně fulltextových tabulek - při odstranění objektu se vyčistí všechny jemu odpovídající záznamy v DB. MariaDB + innodb zcela v pohodě. Hledání je svižné i při hodně komplikovaných query (spoustu podmínek na atributy a vazby, left joiny atd.). Je fakt, že má MariaDB na produkčních serverech nastavené celkem dost RAM (100GB) a vše samozřejmě na SSD (nové servery na PCIe NVMe).

Problém je fulltext. Máme interní indexátor nad atributy textového typu přímo v mysql, ale ten neumí spoustu fulltextových vychytávek, takže bokem defakto elastic search s asynchronní aktualizací z objektové vrstvy a to není úplně dobré. Jenže kvalitní fulltext (více jazyků, přibližná hledání) je opět elasticsearch...

Drží to dobře, asi bych to dneska dělal znovu podobně, noSQL DB zatím pořád nějak nevěřím, mongo mě pro tyto účely rozhodně nepřesvědčilo (máme pro statistiky přístupů, cca 100 mil. objektů). Jenom ten fulltext je problém, snad se nativní fulltext mariadb posune (podpora více jazyků apod...)

Re:Návrh relační databáze
« Odpověď #11 kdy: 25. 04. 2019, 16:54:16 »
Používáme už skoro 20 let defakto ORM uložení do SQL - objekty a vazby mezi nimi.

Tabulka objektů se základními parametry objektů (ID objektu, ID typu objektu, název, datum vytvoření, přístupová práva atd.). ID typu objektu odpovídá příslušné třídě v javě - potomku InfoObject. Přímo třída objektu může nést už byznys kód, protože jsou vytvořené pro konkrétní účel (téma, dokument, uživatel, firma, skupina, obrázek, žádost, atd. atd.).

Pak je evidenční tabulka atributů, která obsahuje typ (string/int/date/JSON) a ID typu atributu. Stále častěji používáme typ JSONAttrib. Opět typu atributu odpovídají třídy v javě.

Každý atribut má vlastní tabulku attr_IDatributu se sloupcem value dle jeho typu a samozřejmě id_obj s navázáním na objekt.

(...)

Pokud to dobře chápu, máte tam Entity–attribute–value model (EAV)? Pokud ano, bylo by dobré zmínit, že to ledaskdo považuje za antipattern. Což samozřejmě neznamená, že to nemůže fungovat, otázkou je pracnost a vlastnosti.

Re:Návrh relační databáze
« Odpověď #12 kdy: 25. 04. 2019, 17:03:56 »
Takový přístup podle mě není správný. N-sloupci vyjadřujete jednu vlastnost, nehledě na to, že musíte provádět další ošetření. Opět nevidím nic špatného na tom, že sloupec ParentId odkazuje do tabulky, která obsahuje řekněme core objektů, a tabulky skupin obsahují jejich vlastnosti.
Podle mne je to přístup, pro jaký byly relační databáze navrženy. Z hlediska relačních databází to není jedna vlastnost, je to několik vlastností, protože se odkazujete na různé tabulky. Relační model vychází z toho, že vše vyjadřujete jako tabulky a vazby mezi tabulkami, nic jako polymorfismus původní relační model nezná.

Já neříkám, že ten váš model je špatný – jenom to není relační model, ale spíš asi objektový, který do relačního modelu serializujete. Na tom není nic špatného, dělá se to tak často, akorát je dobré to vědět, nemyslet si, že mám „silně relační model“, a také k tomu tak přistupovat – např. počítat s tím, že nedokážu prostředky relačního modelu zajistit konzistenci dat. Můžu se ji pokusit zajistit v databázi imperativně (pomocí triggerů nebo procedur), ale relační databáze nejsou úplně nejlepší nástroje pro imperativní programování.

Aplikace je tvořena s důrazem na co největší univerzálnost a obecnost (bohužel). Tedy například parent objektu může být jakýkoliv jiný objekt (pochopitelně jen jeden).
Univerzálnost je v přímém rozporu s tím, k čemu je určený relační model databáze. Opět, není na tom nic špatného, ostatně proto vznikly různé NoSQL databáze – a proto si před nimi kde kdo implementovaly svá key-value nebo entity–attribute–value řešení nad relačními databázemi.

A co jsem měl zmínit nejspíš hned na začátku: Použité technologie (MSSQL+C#) jsou kvůli oblasti trhu, ve které působíme, nedotknutelné.
Jestli se nepletu, má MSSQL slušnou podporu XML. Pak můžete v tabulkách ukládat údaje, podle kterých se vyhledává, a ty zbývající vlastnosti ukládat do XML.

Ale nedá se odpovědět, jak to dělat správně nebo že by měl někdo nějaký zázračný tip. Kdyby to šlo dělat dobře v relačních databázích, nebylo potřeba vymýšlet NoSQL – nebo opačně, ten zázračný tip jsou NoSQL databáze (samozřejmě, že ne každá – NoSQL databáze používají spoustu různých modelů).

Re:Návrh relační databáze
« Odpověď #13 kdy: 25. 04. 2019, 17:48:09 »

Pokud to dobře chápu, máte tam Entity–attribute–value model (EAV)? Pokud ano, bylo by dobré zmínit, že to ledaskdo považuje za antipattern. Což samozřejmě neznamená, že to nemůže fungovat, otázkou je pracnost a vlastnosti.

Přiznám se, že teoretické antipatterny neřeším, zajímají mě praktické požadavky. Snadná rozšiřitelnost do všech stran, podpora spolehlivého dlouhodobého vývoje (žádná reflexe apod, vše typově hlídané) a v neposlední řadě rozumný výkon. Ale ten lze dnes nahonit HW, který je velice levný. Repas server DL580 s 512GB DDR3 12800, 40 jádry a spoustou PCI-e v.3 slotů pro NVMe disky jsme nedávno kupovali za 30k Kč s dopravou. Tichá pracovní stanice Precision T7600 2x octa e-5 xeon 128GB RAM + spoustu PCI-e v.3 vyjde na 21k Kč, s 256GB RAM něco přes 30k. Kolik je to proti měsíčním nákladům na jednoho vývojáře...

Narozdíl od nákladů na vývoj, které jen porostou. Požadavky na změny a nové funkce chodí od byznysu každý den, zatímco ruční zásah do struktury DB jsme nedělali už hodně let. Tabulky atributů si samozřejmě vyrábí ORM samo.

Re:Návrh relační databáze
« Odpověď #14 kdy: 25. 04. 2019, 18:08:22 »
Nechci někomu na potkání vykládat know-how, ani nežádám vyzrazení suprfičur ostatních. Spíš chci dát prostor ostříleným architektům, aby se pochlubili svým originálním přístupem a inspirovali jiné ztracené duše.

No tvl ty budes architekt jak vino. .NET developer, motto "nechci nekomu vykladat sve knowhow". A jaky jsi skromny, chces dat ostanim ostrilenym architektum (jako ty) prostor.

Jsem tu jediny, komu prijde bizarni, ze tady na diskuzni forum prijde clovek s otazkou, kterou zacne jako "nechci nikomy vykladat sve knowhow", a pote co v textu sdeli, ze "Po řadě pokusů a omylů jsme dospěli k řešení, které jistě není dokonalé, ale momentálně splňuje naše požadavky", popise, jak naimplementoval tak strasnou sracku, ze se z toho cloveku uplne jezi vlasy hruzou?

Ja mam dojem, ze tvoji aroganci predchazi snad uz jen tva neschopnost.
« Poslední změna: 25. 04. 2019, 18:12:09 od prihlaseny_uzivatel »