Minule se zde na Zdrojáku rozhořela debata pod tímto článkem. V diskuzi padlo dost argumentů proti SQL i pro SQL. V tomto článku se podíváme na to, jak by vypadal takový databázový návrh pro key-value databázi, a jak moc je odlišný od návrhu pro klasickou sql databázi. Také si shrneme výhody a nevýhody těchto řešení.
Zadání
Mějme takové klasické zadání, na kterém si studenti ve škole trénují návrh SQL databází. V zadání nebudeme zabíhat příliš do detailů a nebudeme ho rozebírat více než je třeba.
Zadání je následující: Chceme vytvořit systém, který bude vypisovat program kin. Program může být týdenní nebo měsíční. V programu je uveden název kina ve kterém se hraje a adresa kina. Dále program bude obsahovat seznam filmů, což znamená, že u každého filmu bude jméno filmu, krátký popis, režisér filmu a také rok vzniku filmu. Dále bude možno vyhledávat, které kino hraje konkrétní film.
Analýza
Pokud půjdeme na věc klasicky, jak nás to naučili ve školních škamnách, tak okamžitě rozpoznáme entity Kino a Film s tím, že entita Kino má atributy adresa a název. Entita Film pak rok, režisér, jméno filmu, popis. Tyto entity pak mají vztah m:n, protože Kino může hrát (třeba i nehrát, to zadání neříká) libovolný počet filmů, a stejně tak film může být hrán v libovolném počtu kin. E-R diagram pak bude vypadat následovně:

Z tohoto diagramu by v SQL vznikly 3 tabulky. Tabulka Kino pro záznam informací o kinech, tabulka Film pro záznam informací o filmech a tabulka Představení, která by říkala, který film se hraje ve kterém kině a kdy. Hotovo. Nyní napsat SQL dotazy a nějak ta data prezentovat a máme vystaráno. Víceméně si vystačíme s dvěma dotazy – první vypíše program a druhý vyhledá kino podle názvu filmu.
Nyní se podíváme co udělat s tím samým případem, když máme k dispozici pouze key-value databázi. Nevím o žádné speciální metodice, podle které bych to navrhl, takže se přidržím předchozího návrhu, a ten denormalizuji. Do databáze uložím data tak, jak by vypadal výsledek provedeného SQL dotazu z předchozího příkladu. Jedná se tedy o data, která přímo vidí uživatel. Při výběru a výpisu dat nebude prováděna jiná operace než jejich formátování do výsledné podoby (například HTML stránka apod).
Začneme tím, jak bude vypadat uložený program kin. V zadání jsou dvě možnosti jak vypsat program: týdenní a měsíční. Jestli se jedná o týdenní či měsíční bude rozlišovat klíč. Každý záznam bude obsahovat Kino a jeho atributy a pak program, tedy seznam filmů s časem, kdy se hrají. V JSON notaci by zjednodušený měsíční program kin mohl vypadat následovně:
| klíč | hodnota |
| 01/2010 | [{Kino:{Adresa:Václavák,Nazev:Kino Václavák}},{Program}] |
Obdobný případ je výpis týdenních programů kin. Jinak bude vypadat klíč (týdnů je více než měsíců), ale hodnota bude mít formát stejný.
Ještě nám zbývá dodělat výpis seznamu kin, které hrají konkrétní film. To bude trochu oříšek. Máme dvě možnosti, jak se k tomu postavit. Jedna z nich je, že to budeme vyhledávat přímo buď v týdenních nebo měsíčních záznamech, a druhá možnost je, že si toto dáme stranou, film bude fungovat jako klíč a pod tímto klíčem bude uložen seznam všech kin, které kdy ten film uvedly. To by mohlo vypadat následovně:
| klíč | hodnota |
| 7 statečných | [{Adresa:Václavák,Nazev:Kino Václavák,Datum:02/01/2010 15:00}] |
Úprava schématu
Tak by to vypadalo, pokud by se zadání neměnilo a schéma, které jsme dostali na začátku, by bylo stejné po celou dobu používání aplikace. Reálně to tak není a vždy dochází k nějaké úpravě schématu. Každá úprava bude vyžadovat menší či větší programátorský zásah do aplikace, a to jak u NoSQL, tak i u klasické relační databáze. U relačního schématu musíme také provést změny databáze, které mohou být netriviálního charakteru. U NoSQL to není nutnou podmínkou. Ukážeme si proč.
Začneme zlehka, řekněme, že se nám sešlo více filmů, které mají více než jednoho režiséra. Takže je potřeba rozšířit naše schéma o tabulku režisér, a tu přes klíč připojit k filmům. Což znamená poměrně radikální přestavbu databáze, která může i chvilku trvat v závislosti na počtu řádek v databázi. A to došlo pouze k relativně malé změně, že potřebujeme více režisérů. Z hlediska NoSQL je to jedno, tak se do databáze uloží více režisérů a aplikace se upraví, aby s tím počítala. Hotovo.
Tady jistě někdo namítne, že od toho se dělá analýza a to byla chyba při návrhu. Ano, u tohoto příkladu se dá diskutovat, že to byla chyba při návrhu. Jenže co má dělat takový SaaS poskytovatel? SaaS aplikace se vyznačují tím, že jedna instance aplikace obsluhuje více zákazníků. Často se stane, že zákazník chce nějakou malou změnu (z pohledu zákazníka, u poskytovatele to může vyvolat menší paniku). Poskytovatel nemůže jen tak měnit schéma, nehledě na to, že požadavky zákazníků si často protiřečí. Takže musí myslet na nějakou možnost přizpůsobení. Což se děje různým způsobem, buď přímo použitím NoSQL databáze nebo návrhem SQL schématu tak, aby se s touto možností vyrovnal. (Dobrý příklad je třeba open source wiki – XWiki)
Výhody a nevýhody
V případě key-value je vidět, že budeme čelit velké redundanci dat a udržování integrity dat bude úkol pro aplikaci. Jakákoliv oprava dat bude znamenat prohledat všechny záznamy, kde se daná data nacházejí. Což bude netriviální operace. Na druhou stranu bude výpis dat velmi rychlý, stejně tak zápis. Máme také možnost snadno přidat další atributy k filmům či kinům. Tyto atributy mohou být třeba jen dočasné. Tyto dočasné atributy bude muset umět obsloužit aplikace a vlastně bude i nositelem jejich popisu. V závislosti na zvolené databázi (Redis,TokyoCabinet, Project Voldemort apod.) dostaneme i dobře škálovatelné řešení.
V případě relačního modelu máme známé výhody: Data jsou snadno udržovatelná, dobře se udržuje i datová integrita. Data také budou zabírat méně místa na disku, protože nejsou redundantní. Změna výpisu může znamenat pouze změnu SQL dotazu, nebude třeba přegenerovat celou databázi. Máme také k dispozici více materiálu o tom, jak klasickou SQL databázi navrhovat a udržovat v chodu. Na druhou stranu, pokud se vyskytnou speciální atributy, bude to znamenat změnu schématu, což u více záznamů není operace na pár vteřin. Ukládání dat bude pomalejší (ACID, dokud nejsou data uložena ve všech tabulkách, nelze zapisovat další).
Oba modely je možné zkombinovat a dostat tak výhody obou. Tj data budeme mít uložena pěkně relačně, takže se nám bude dobře udržovat integrita dat, a pro výpis dat budeme používat key-value databázi. Což třeba dělá Facebook (data jsou uložena v relační databázi, ale většina je cachována pomocí memcached) nebo LinkedIn, které stojí za Project Voldemort.
NoSQL nejen na straně serveru
Mohlo by se zdát, že podobné principy jsou záležitostí pouze pro server, jenže blízká budoucnost vás vyvede z omylu. Lokální úložiště, jak je definuje HTML 5, jsou přesně typem NoSQL. A vzhledem k jejich možnostem a směřování vývoje k poměrně rozsáhlým webovým aplikacím je jisté, že velká část dat se bude u klienta uchovávat. Byť třeba jen proto, že mu zrovna vypadlo připojení k internetu. Proto je dobré se již teď zabývat tím, jak data ukládat a jak v nich lehce vyhledávat.


Přehled komentářů