Disclaimer: Článek je překladem článku How to move from MySQL to CouchDB z blogu CouchOne. Překlad i s originálními ilustracemi vychází s laskavým svolením společnosti CouchOne. Autor článku pracuje v CouchOne jako člen výboru a viceprezident pro dokumentaci, v minulosti psal dokumentaci k MySQL.
Začneme tím, že se podíváme, jak lze strukturu databáze v MySQL převést na CouchDB, a jak se dotazy na CouchDB liší od způsobu používaného v MySQL.
Úvodní zamyšlení nad strukturou dat
MySQL (a další SQL databáze a jiné databáze založené na tabulkách) vás nutí uvažovat o datech jako o tabulkách. Všechna vaše data tvoří tabulku a při ukládání složitých struktur může být jedna informace rozložena do více tabulek. Pro některé aplikace a datové typy je to naprosto logická a rozumná forma uložení dat a přístupu k nim. Ale někdy tabulková struktura příliš neodpovídá datům, které chcete ukládat.
Ukažme si to na typickém příkladu, databázi receptů. To je něco, co dobře znám, protože server Cheffy.com je postavený na MySQL. Jádro databáze tvoří tabulka nazvaná recepty (Recipe), která obsahuje název receptu, podtitul, popis a počet porcí. Další údaje vztahující se k receptu, jako je seznam přísad (Ingredients), postup práce (Method), metadata a klíčové slova (Keywords), jsou uložené v dalších tabulkách, navázaných k samotnému receptu pomocí unikátního ID receptu. Velmi zjednodušeně je to vidět na následujícím obrázku.
Tato struktura může mít své výhody – určité operace mohou být například velmi jednoduché a přímočaré. Například: chcete najít všechny recepty, mezi jejichž přísady patří „mrkev“? Můžete nad tabulkou přísad vykonat dotaz na „mrkev“, a z něj získat seznam odpovídajících receptů. Za pomoci spojování tabulek můžete získat seznam receptů, jejich názvů a dalších informací z tabulky recepty tak, že budete hledat v tabulce přísady a přes ID receptu spojíte tuto tabulku s tabulkou recepty.
Zatímco tento způsob vyhledávání je jednoduchý, získání všech údajů o receptu, například pro jeho zobrazení uživateli, může být skutečně složité. Šlo by to jedním dotazem, ale někdy to bývá snazší pomocí více dotazů: jedním k němu získat údaje z tabulky recepty, druhým jeho přísady, dalším metadata atd. To vše je automaticky vykonáno v rámci aplikační vrstvy a výsledkem je objekt, který se pak použije jako základ pro formátované zobrazení receptu uživateli.
Ve většině aplikací je buď pro tento účel vytvořena speciální vrstva, a nebo se použije jeden z mnoha objektově-relačních mapovacích systémů, které mapují data ze struktury tabulek na vrcholový objekt, se kterým pak pracuje aplikace (a uživatel). Recepty jsou jen jedním z příkladů, obdobně je na tom i mnoho jiných různých aplikací, včetně fakturace (faktura, dodavatel, místo určení, položky faktury) a příspěvků na blogu (obsah příspěvku, klíčové slova, autor, komentáře).
Tento přístup založený na tabulkách není z principu špatný, ale v této situaci je zásadní informace rozložena do více tabulek, a to vede k nutnosti synchronizovat spolu tyto tabulky. Například, co se má stát, pokud se smaže záznam? Musíte smazat všechny další záznamy, které se na něj mohly odkazovat (buď ručně, nebo pomocí klauzule ON DELETE CASCADE). Obdobně také při načítání údajů jednoho receptu budete muset nakonec provést 5-10 dotazů na data.
CouchDB volí jiný přístup. Namísto více tabulek, do kterých se ukládají různé typy informací, do CouchDB ukládáte jeden typ struktury dat ve formátu JavaScript Object Notation (JSON). Formát JSON umožňuje sloučit jakkoliv složitou strukturu atributů, polí, objektů a skalárních typů do jednoho záznamu. To znamená, že nyní můžete vaši starou entitu, rozprostírající se skrz několik tabulek, vyjádřit jako jeden „dokument“.
{ "title" : "Carrot and Coriander Soup" "servings" : 4, "subtitle" : "Delicious with wholemeal bread", "ingredients" : [ { "amount" : 250, "ingredient" : "Carrots", "measure" : "g" }, { "amount" : 75, "ingredient" : "Coriander", "measure" : "g" }, { "amount" : 250, "ingredient" : "Vegetable Stock", "measure" : "ml" } ], "method" : [ { "step" : 1, "instruction" : "Chop carrots" }, { "step" : 2, "instruction" : "Cook all ingredients in pan" }, { "step" : 3, "instruction" : "Liquidize" } ], }
Teď je vše, co můžete chtít dělat s vaším receptem, na jednom místě, a můžeme ho načíst z databáze CouchDB v rámci jedné operace.
Databáze nemá žádnou definici dat či obsahu – každý dokument v databázi CouchDB může obsahovat cokoliv v jakékoliv struktuře. Můžete ale při ukládání dokumentu do databáze ověřit jeho strukturu provedením validační procedury. Validace se může týkat jak položek, tak jejich obsahu.
Také si uvědomte, že tato neexistence pevné struktury dat přináší větší volnost v tom, jaké údaje ukládáte, a jak. Pokud chcete do vašeho dokumentu obsahujícího recept přidat nový oddíl pro uchování dat, kdo recept vložil, stačí jen rozšířit strukturu dokumentu.
Neexistuje také představa více tabulek. Existuje jen databáze, a dokumenty obsažené v této databázi. Pokud chcete podporovat různé typy údajů v jedné databázi, pak můžete přidat další položku do dokumentu. Pro identifikaci receptu byste například mohli použít:
{ "type" : "recipe", "title" : "Carrot and Coriander Soup" "servings" : 4, "subtitle" : "Delicious with wholemeal bread", ... }
Tato identifikace typu záznamu může být použita v jiných částech databáze pro rozpoznání (a výběr) dat, které se mají nahrát.
Pokud je všechno dokumentem, jak vybrat seznam záznamů?
V první části jsem ukázal, jak sestavit jednoduchý SQL dotaz, který z MySQL databáze vybere seznam všech receptů, mezi jejichž přísady patří mrkev. V MySQL se to udělá tak, že se vyhledává v tabulce přísad a pomocí získaného ID receptů se tato tabulka spojí s tabulkou recepty, z níž lze vyčíst názvy receptů. Kvůli zlepšení rychlosti provádění dotazu byste obvykle použili index, který ušetří postupné procházení jednoho záznamu za druhým.
CouchDB považuje všechno za dokumenty, a neposkytuje způsob, jak hledat podle určitého sloupce tabulky, protože v ní nejsou žádné sloupce ani tabulky. Když ale její záznamy nemají pevnou strukturu (a databázový engine nedokáže identifikovat datové položky v dokumentu bez pevné formy), jak pak provést operace, které normálně pracují nad seznamem nebo tabulkou? Všechny dotazy, počínaje jednoduchým „Vypiš všechny recepty“ až po „Najdi všechny recepty, do kterých patří mrkev“, totiž spoléhají na to, že někde existuje nějaký seznam.
CouchDB podporuje databázový konstrukt nazvaný pohled (anglicky view). Pohledy v CouchDB jsou v principu velmi podobné pohledům v MySQL, jen s tím rozdílem, že v CouchDB nejsou pohledy pouze jednou z více možností, ale jsou jedinou cestou, jak získat z databáze seznam dokumentů. Pohled ve skutečnosti určuje tři věci:
- strukturu dat obsažených v pohledu. Lze na ni pohlížet stejně jako na definici struktury tabulky, tak jak se zadává v MySQL.
- sloupce a data, v kterých lze vyhledávat. Výstupem pohledu jsou totiž dvě položky: klíč a seznam hodnot. Klíče tedy určují způsob, jak lze v databázi vyhledávat požadovaný obsah.
- index struktury a klíčů. Tento index se použije pro zrychlení vyhledávání dat v pohledu.
Pohledy jsou definovány v návrhovém dokumentu, pomocí JavaScriptu, prostřednictvím funkce, která bere dokument jako parametr. Při vytváření pohledu je pak této funkci postupně předán každý dokument v databázi, a ta vygeneruje údaje, které budou výstupy pohledu. Z tohoto JavaScriptového kódu není třeba mít obavy, neprovádí se na klientovi, ale na serveru.
Když se na chvíli vrátíme k MySQL, dotaz (bez klauzule WHERE) vybere sloupce, které mají být vráceny, a vytvoří seznam odpovídajících řádků, který je jeho výstupem. Ukažme si to na SQL dotazu:
Když je dotaz prováděn MySQL, tak MySQL server z informací v tabulce (popř. tabulkách) vytvoří seznam záznamů (a jejich sloupců), které mají být vráceny, takto:
V CouchDB pohled vytvoří seznam záznamů z jednotlivých dokumentů. Vedlejším produktem tohoto procesu je index. Výsledkem je tedy seznam všech údajů, které byly pomocí pohledu vygenerovány z existujích dokumentů.
V MySQL se při provádění klauzule WHERE index (snad) použije k tomu, aby byly vybrány požadované záznamy:
V CouchDB je vygenerovaný pohled vlastně tabulkou, a když je nad pohledem prováděn dotaz, CouchDB použije hodnoty klíčů (a související index, byl vygenerován jako vedlejší produkt vytvoření pohledu) pro výběr požadovaných záznamů:
Tento způsob určení tabulek, nad kterými budou prováděny dotazy, umožňuje zjednodušit a zoptimalizovat získávání údajů z databáze. Ale zároveň také znamená, že je potřeba více popřemýšlet nad tím, jaké dotazy budou nad databází prováděny.
Příště nás čeká…
Teď víte, jak MySQL uchovává údaje a jak na ně lze tvořit dotazy, a jak mohou být tyto vědomosti k užitku při přechodu databáze na CouchDB. Příště začneme podle toho, co jsme se dnes dozvěděli, sestavovat dotazy, a podíváme se také na pokročilejší dotazy a na proces změny databáze.
Přehled komentářů