Portál AbcLinuxu, 30. dubna 2025 23:50
V diskusi ke zprávičce Kampaň za záchranu MySQL jsem byl partou zasloužilých profesionálů bryskně odhalen jako prasič a neschopný programátor, a to na základě několika málo příspěvků (které začaly nevinným flamebaitem, jak je v pokleslých diskusích zvykem). Přímo se mi zatočila hlava, když jsem si představil, co by o mně tito pánové dokázali zjistit, kdybych jim nabídl ke studiu trochu víc materiálu – řekněme takový krátký seriálek o bezschémových databázích? Pohodlně se usaďte, zapomeňte vše, co jste si o databázích doteď mysleli, kurz kvalitního prasení právě začíná.
UPDATE: seriál o CouchDB nakonec vyšel na ábíčku, zbaven výpadů vůči SQL. Díky!
Půjdeme na to čistě prakticky, teorii si můžeme nechat na později. Jednou z dneska nejčastějši zmiňovaných "alternativních" databází je CouchDB. Aktuální verze je 0.10.1, kterou najdete kupříkladu v Debianu unstable. V testingu je 0.10.0, což nám postačí, takže aptitude install couchdb
a s chutí do toho; uživatelé jiných distribucí si snad poradí sami, případně se obrátí na wiki. Lehký přehled o vnitřnostech získáte třeba v technical overview – pro nás to nebude nutné, ale zájemcům vřele doporučuju. CouchDB se mimochodem používá například jako lokální úložiště dat pro Ubuntu One (viz též desktopcouch), což znamená, že vydáním Ubuntu 9.10 se zvýšil podíl instalací Erlangu na osobních počítačích minimálně o stovky procent
CouchDB má jediné API: JSON přenášený přes HTTP. Jop, je to tak, můžete si pohrát třeba z příkazové řádky, a HTTP klienta najdete snad pro jakýkoliv programovací jazyk. Server poslouchá na portu 5984, takže pro seznámení:
$ curl -X GET http://localhost:5984/ {"couchdb":"Welcome","version":"0.10.1"} $ curl -X GET http://localhost:5984/_all_dbs []
Aha, ještě žádnou databázi nemáme vytvořenou! To snadno napravíme. API je RESTové, vytvořit novou kolekci objektů znamená volat PUT. A když jsme v tom, smazání je pochopitelně DELETE.
$ curl -X PUT http://localhost:5984/pokus {"ok":true} $ curl -X GET http://localhost:5984/_all_dbs ["pokus"] $ curl -X DELETE http://localhost:5984/pokus {"ok":true} $ curl -X GET http://localhost:5984/_all_dbs []
Poznatek: "systémové" identifikátory začínají podtržítkem.
Na ten DELETE na chvilku zapomeňme, řekněme, že tedy máme databázi pokus
. Jen tak na hraní. Mějme dokument… no nějaký pěkný, třeba tenhle:
{"type": "book", "author": "Dan Simmons", "name": "Drood"}
Co s ním?
$ curl -X POST -d '{"type": "book", "author": "Dan Simmons", "name": "Drood"}' http://localhost:5984/pokus {"ok":true,"id":"c49a19e0c4fefe86bbab6e12e2d3419f","rev":"1-4ffc368db414b81bf524c6d4c421b93f"}
POST volaný na kolekci znamená vytvořit v ní nový objekt a automaticky mu přiřadit ID. Což se také stalo:
$ curl -X GET http://localhost:5984/pokus/c49a19e0c4fefe86bbab6e12e2d3419f {"_id":"c49a19e0c4fefe86bbab6e12e2d3419f","_rev":"1-4ffc368db414b81bf524c6d4c421b93f", "type":"book","author":"Dan Simmons","name":"Drood"}
(Pro snazší čtení odřádkovávám a odsazuji dvěma mezerami.)
Now come on, it can't be that simple, can it? Poznatek: CouchDB patří mezi dokumentové databáze, kterým není nutné předem říkat, jaká bude struktura ukládaných dat. Datové schéma je čistě věcí aplikace.
Řekněme, že bychom chtěli ukládat i žánrové zařazení. Nebo spíš žánrová zařazení, těch může být vždycky víc:
$ curl -X PUT -d '{"_id":"c49a19e0c4fefe86bbab6e12e2d3419f","_rev":"1-4ffc368db414b81bf524c6d4c421b93f", "type":"book","author":"Dan Simmons","name":"Drood", "genres": ["fantasy", "thriller", "detektivka"]}' http://localhost:5984/pokus/c49a19e0c4fefe86bbab6e12e2d3419f {"ok":true,"id":"c49a19e0c4fefe86bbab6e12e2d3419f","rev":"2-fa897debf5c1a63193f121798e85b6e3"}
Tak moment: pokud relační bohy pořád ještě netrefil šlak, teď by měl rovnou dvakrát. Vždyť já porušuju první normální formu! Jako jednu z položek jsem uložil seznam (když si tedy odmyslím, že celý dokument je vlastně mapa…). Ostatně většina dnešních relačních databází potichu nabízí datový typ pole, jako nóbl vychovaná dáma, která se v době manželovy nepřítomnosti za pár šupů prodává přístavním dělníkům – akorát tady si můžu do toho seznamu uložit klidně další mapy a tak dál. Tady si na nic nehrajeme, když se ukáže, že je to špatná volba, je to můj problém. Pokud se přenesu přes tohle: k čertu, neměly by ty žánry být někde v číselníku a u knihy jenom odkazy do něj? Hm, člověk nikdy neví, tak prozatím řekněme, že žánry jsou pro nás něco jako tagy na webu, a uvidíme, co dál.
Ostatně, když jsme u toho, co sakra ten autor? Ten by přece určitě měl být uložený samostatně a u knihy by na něj měl být jen odkaz, ne? Wow. V jednom mém oblíbeném webovém knihkupectví například vůbec nemají stránky autorů a umí podle jejich jmen jen vyhledávat.
A protože v tuhle chvíli se ctihodní kmetové chytají za hlavu a formulují moudré věty o tom, že bych se nejdřív měl jít projít a přemýšlet, co vlastně chci programovat, na chvilku zpomalíme a podíváme se na záhadné položky _id
a _rev
. _id
je, inu, ID, čili primární klíč, jak se říkalo za starých dobrých zapomenutých časů. ID si můžu nechat generovat od CouchDB při vytváření nových dokumentů, jako tomu bylo výše (v takovém případě se vyrobí nový GUID, tedy vlastně UUID, ale tohle slovo prostě nejde vyslovit bez zřetelného falického podtextu, takže se uchyluju k termínu z nepřátelského tábora Microsoftu), nebo si ho zadat sám.
$ curl -X PUT -d '{"type": "book", "author": "Orson Scott Card", "name": "Enderova hra", "genres": ["sci-fi", "humanismus"]}' http://localhost:5984/pokus/enderova-hra {"ok":true,"id":"enderova-hra","rev":"1-0b1b7e88639474892f4eb950bf139e27"} $ curl -X GET http://localhost:5984/pokus/enderova-hra {"_id":"enderova-hra","_rev":"1-0b1b7e88639474892f4eb950bf139e27","type":"book", "author":"Orson Scott Card","name":"Enderova hra","genres":["sci-fi","humanismus"]}
Automatické generování GUIDů je víc než vhodné minimálně v případě, kdy je databáze "distribuovaná" (CouchDB disponuje hezkou funkcí replikace s řešením konfliktů, ale tím se teď zabývat nebudeme). Naopak číselná ID v rostoucí posloupnosti mohou být pro databázi příjemnější kvůli způsobu, jak jsou ukládána a vyhledávána data (už jsem říkal, že základní a vlastně jedinou diskovou strukturou CouchDB je B-strom?).
A co to _rev
? Jistě, je to od slova revision, což ovšem neznamená, že by se CouchDB dala použít jako verzovací systém. Číslo revize se používá k řešení současného přístupu k datům: už výše jste viděli, že když chci dokument změnit, musím ho poslat tak, jak jsem ho dostal. CouchDB povolí zápis jen tehdy, pokud se číslo revize v ukládaném dokumentu shoduje s aktuálně platným číslem revize v databázi.
$ curl -X PUT -d '{"_id":"enderova-hra","_rev":"1-0b1b7e88639474892f4eb950bf139e27", "type":"book","author":"Orson Scott Card","name":"Enderova hra","genres":["sci-fi","humanismus"], "stars": "5/5"}' http://localhost:5984/pokus/enderova-hra {"ok":true,"id":"enderova-hra","rev":"2-823eb2f692da425220f17b96b231082b"} $ curl -X PUT -d '{"_id":"enderova-hra","_rev":"1-0b1b7e88639474892f4eb950bf139e27", "type":"book","author":"Orson Scott Card","name":"Enderova hra","genres":["sci-fi","humanismus"], "stars": "6/5"}' http://localhost:5984/pokus/enderova-hra {"error":"conflict","reason":"Document update conflict."} $ curl -X PUT -d '{"_id":"enderova-hra","_rev":"2-823eb2f692da425220f17b96b231082b", "type":"book","author":"Orson Scott Card","name":"Enderova hra","genres":["sci-fi","humanismus"], "stars": "6/5"}' http://localhost:5984/pokus/enderova-hra {"ok":true,"id":"enderova-hra","rev":"3-1be8a2371b004f49b284061433ba9b48"}
Starou revizi je stále možné číst, ovšem pouze tehdy, pokud je v databázi ještě dostupná.
$ curl -X GET http://localhost:5984/pokus/enderova-hra?rev=1-0b1b7e88639474892f4eb950bf139e27 {"_id":"enderova-hra","_rev":"1-0b1b7e88639474892f4eb950bf139e27","type":"book", "author":"Orson Scott Card","name":"Enderova hra","genres":["sci-fi","humanismus"]} $ curl -X POST http://localhost:5984/pokus/_compact {"ok":true} $ curl -X GET http://localhost:5984/pokus/enderova-hra?rev=1-0b1b7e88639474892f4eb950bf139e27 {"error":"not_found","reason":"missing"}
Poznatek: CouchDB používá multigenerační architekturu a řešení souběžných přístupů je tedy optimistické (žádné zámky). Garbage collector (compaction) je AFAIK nutné volat ručně (viz též wiki); po dobu jeho běhu lze databázi normálně používat.
Bližší informace o revizích dokumentu získáte použitím parametrů revs=true
nebo revs_info=true
:
$ curl -X GET http://localhost:5984/pokus/enderova-hra?revs_info=true {"_id":"enderova-hra","_rev":"3-1be8a2371b004f49b284061433ba9b48","type":"book", "author":"Orson Scott Card","name":"Enderova hra","genres":["sci-fi","humanismus"], "stars":"6/5","_revs_info":[ {"rev":"3-1be8a2371b004f49b284061433ba9b48","status":"available"}, {"rev":"2-823eb2f692da425220f17b96b231082b","status":"missing"}, {"rev":"1-0b1b7e88639474892f4eb950bf139e27","status":"missing"} ]}
Obdobně funguje mazání: je to vlastně vytvoření nové revize.
$ curl -X DELETE http://localhost:5984/pokus/enderova-hra {"error":"conflict","reason":"Document update conflict."} $ curl -X DELETE http://localhost:5984/pokus/enderova-hra?rev=3-1be8a2371b004f49b284061433ba9b48 {"ok":true,"id":"enderova-hra","rev":"4-d71e7ad84ec3801b0504b739e925e8b7"} $ curl -X GET http://localhost:5984/pokus/enderova-hra {"error":"not_found","reason":"deleted"}
Nu, takže CRUD máme za sebou, co dál? Ovšem, dotazy. SQL? Ale kdeže, JavaScript! JavaScript a MapReduce. Zkusme do toho skočit po hlavě:
// map function(doc) { if (doc.type == "book" && doc.genres) { for (var genre in doc.genres) { emit(doc.genres[genre], doc.name); } } }
Co to je? To myslím vážně? Si snad dělám kozy, ne? Tak postupně: CouchDB má pohledy. Ty pohledy jsou definovány jednou nebo dvěma funkcemi v programovacím jazyce (konkrétně v JavaScriptu, ale rozhraní je obecné a existuje podpora pro další jazyky, viz wiki). Názvy těch funkcí pocházejí z funkcionálního světa: map a reduce (resp. fold), a nesou si z něj ještě jednu vlastnost: musí být idempotentní. To zjednodušeně znamená, že nesmí nic změnit (pro jeden dokument musí vždy vrátit tu samou hodnotu), a to zase zjednodušeně vede ke krásným důsledkům: pohledy lze počítat inkrementálně a paralelně. Funkce map je povinná a slouží k filtrování a transformování. Je zavolána pro každý dokument v databázi a sama každým voláním emit generuje jednu položku pohledu: pár klíč -> hodnota (v příkladu výše pár žánr -> název knihy). Funkce reduce je nepovinná, takže ji na chviličku vynecháme. Výsledky se ukládají na disk (takže ten pohled je vlastně materializovaný), a to vždy seřazené podle klíče (takže je to vlastně i index).
Teď jak tedy tu funkci do databáze dostat. Z řádky už mě to nebaví, takže si v prohlížeči otevřu http://localhost:5984/_utils, kde se nachází Futon, standardní GUI ke CouchDB. Futon je z velké části JavaScriptová aplikace, s CouchDB komunikuje AJAXem stejným způsobem, jako jsme si to předvedli výše. Vlezu do databáze pokus
a vpravo nahoře zvolím View: Temporary view... Do pole Map Function vložím kód uvedený výše a tlačítkem Run si můžu hned zobrazit výsledky:
To je dočasný pohled, ten ještě není uložený na disku a pokaždé se počítá znovu. Tak tedy Save As..., Design Document: _design/books, View Name: by_genre, a Save. Když pak opět vpravo nahoře zvolím View: All documents, vidím, že v databázi vznikl nový dokument s ID _design/books
. Zkuste se podívat na jeho obsah, případně pod záložkou Source se skrývá čistý JSON.
$ curl -X GET http://localhost:5984/pokus/_design/books/_view/by_genre {"total_rows":3,"offset":0,"rows":[ {"id":"c49a19e0c4fefe86bbab6e12e2d3419f","key":"detektivka","value":"Drood"}, {"id":"c49a19e0c4fefe86bbab6e12e2d3419f","key":"fantasy","value":"Drood"}, {"id":"c49a19e0c4fefe86bbab6e12e2d3419f","key":"thriller","value":"Drood"} ]} $ curl -X GET 'http://localhost:5984/pokus/_design/books/_view/by_genre?key="thriller"' {"total_rows":3,"offset":2,"rows":[ {"id":"c49a19e0c4fefe86bbab6e12e2d3419f","key":"thriller","value":"Drood"} ]} $ curl -X GET 'http://localhost:5984/pokus/_design/books/_view/by_genre?startkey="a"&endkey="n"' {"total_rows":3,"offset":0,"rows":[ {"id":"c49a19e0c4fefe86bbab6e12e2d3419f","key":"detektivka","value":"Drood"}, {"id":"c49a19e0c4fefe86bbab6e12e2d3419f","key":"fantasy","value":"Drood"} ]}
Parametry key
, startkey
a endkey
musí být platný JSON, proto ty uvozovky. Takže umíme hledat podle hodnoty i podle rozsahu; o dalších možnostech si můžete přečíst na wiki. Tohle vypadá oproti SQL jako pěkná pakárna, pravda? Inu, dynamicky typované programovací jazyky si za svoje služby vybírají jistou daň, bezschémové databáze taktéž. A ve chvíli, kdy se v SQL dostaneme k dotazovatelným procedurám, rozdíly se téměř stírají. Podobně jako materializované pohledy to má výhodu výborného výkonu: není potřeba nic počítat, stačí jen číst.
Dál: co si trochu zaredukovat? Nepovinná funkce reduce slouží k agregování. Řekněme, že chceme pro každý žánr vědět, kolik knih do něj patří. Zkusíme si takový lehký myšlenkový veletoč:
// map function(doc) { if (doc.type == "book" && doc.genres) { for (var genre in doc.genres) { emit(doc.genres[genre], 1); } } } // reduce function(keys, values, rereduce) { // log({"keys": keys, "values": values, "rereduce": rereduce}); return sum(values); }
Tak tohle už je trochu zvláštní – kdo nikdy neslyšel o MapReduce, bude asi pořádně zmatený. Zkusme trochu osvětlit princip: pro každý dokument systém zavolá mapovací funkci, která může emitovat libovolně mnoho dvojic <klíč; hodnota>, to už jsme viděli. Všechny takto vyrobené dvojice se vezmou, vyrobí se z nich množina dvojic <klíč; seznam všech hodnot emitovaných pro tento klíč> a pro každou z těchto dvojic se následně zavolá redukční funkce. Ta musí být komutativní a asociativní, a musí vždy vrátit právě jednu hodnotu (v našem případě je to číslo, ale může to být klidně i seznam apod.), proto se jí říká redukční.
V našem případě funkce map vygeneruje pro každou knihu v každém žánru jednu jedničku, a funkce reduce ty jedničky po jednotlivých žánrech sčítá.
$ curl -X GET http://localhost:5984/pokus/_design/books/_view/genres_count?group=true {"rows":[ {"key":"detektivka","value":1}, {"key":"fantasy","value":1}, {"key":"thriller","value":1} ]}
Proti SQL vážně směšné, že? Hlavně proto, že výklad výše je ve skutečnosti lež: redukce v CouchDB neprochází prostřední fází (seskupování hodnot podle klíče). Parametr keys
obsahuje pole různých emitovaných klíčů (a také ID dokumentů, ze kterých byly klíče emitovány), parametr values
pole odpovídajících emitovaných hodnot. Protože pohledy se v CouchDB vyhodnocují inkrementálně, je tu ještě parametr rereduce
: je-li jeho hodnota false
, platí vše, co bylo dosud řečeno, avšak je-li jeho hodnota true
, znamená to, že redukční funkce musí zkombinovat výstupy předchozích volání sebe sama. Tyto výstupy jsou v parametru values
, v parametru keys
je null
. Protože tohle už je poměrně vysoká magie (výše je ukázáno jen základní použití), odkazuji na wiki a přidávám jeden užitečný tip: jak vidno na zakomentovaném řádku v kódu výše, při vyhodnocování javascriptových funkcí v CouchDB lze logovat. (Zkuste si to, log je ve /var/log/couchdb/couch.log
).
Každopádně když nic jiného, můžete těchto pár odstavců brát jako ukázku způsobu, kterým se dneska hromadně zpracovávají obrovské objemy dat – na ad hoc dotazování to ovšem stojí za starou belu. Pro tyto účely lze s výhodou využít couchdb-lucene, i když například vývojáři Mozilla Raindropu používají Megaview (mimochodem Raindrop doporučuju k nahlédnutí).
Poznatek: indexované MapReduce pohledy jsou silná zbraň, ale v ad hoc dotazování je CouchDB slabý.
A to by bylo dneska všechno. Příště vyřešíme problém s ukládáním autora, který jsme dnes nechali otevřený, a ukážeme si, že z CouchDB lze přímo servírovat HTML (tak jak to Oracle umí už léta). Použijeme také slovo "join". Kvalitnímu prasení zdar!
P.S.: nejlepším sci-fi seriálem všech dob je vskutku Doctor Who, a to z jednoho prostého důvodu: nikdo jiný nedokázal odpovědět na otázku, kdo je Černá dáma ze Shakespearových sonetů!
Tiskni
Sdílej:
Nojo, ale ty sebemrskačské poznámky o prasení a tak se zají po prvním přečteníOny se hlavně zají ty nejapné poznámky hraničící s útoky v každé reakci na tvůj komentář.
Parametry u zbozi jsou hodne spatny priklad, to opravdu neni "neznama struktura", kvuli ktere by bylo potreba neustale "menit nebo zeslozitovat DB schema". Ale na to prijdete sam az vas pozadaji, abyste do vaseho eshopu doplnil napr. hledani a razeni podle parametru...
V několika knižních databázích jsem viděl jednoho a toho samého autora zadaného vícekrátNormální je, že aplikace nabízí uživateli zadání autora z číselníku, může mu i napovídat jeho jméno podle zadání prvních pár písmen, případně se musí nejdřív vytvořit autor a pak teprve se může použít (a tato procedura je trochu uživatelsky nepřívětivá, aby uživatel nezadával spousty nových autorů a radši se nejdřív podíval, jestli už tam ten autor není). Totéž platí pro žánry. Jenže jak tohle udělat v té nenormalizované „databázi“? Pokud tam má být nějaká nápověda, musí se projet všechny záznamy a z jejich polí vytahat všechny žánry (či jména autorů), pak zahodit duplicity (to se všechno dělá v aplikaci?) a pak je zobrazit uživateli. Zatímco když je databáze aspoň trochu normalizovaná, tak máme číselník žánrů (nebo autorů) a projíždí se vždy jen tahle relativně malá tabulka.
v NoSQL se zjišťují už při zápisuTakže musím předem vědět, jaké dotazy na databázi budu klást? Trochu omezující, ne? (ostatně v relačních DB to není nic nového – materializované pohledy nebo triggery a tabulky s denormalizovanými daty)
With CouchDB, no schema is enforced, so new document types with new meaning can be safely added alongside the old.takže tam bude asi pěkný guláš a moc z toho nevykouká. Leda že by si projel všechny dokumenty a zjistil, které jsou „new“ a které „old“ případně nějaké úplně jiné, rozdělil si je ve své hlavě na nějaké skupiny a snažil se zachytit jejich struktury. Přijde mi, že si tu někdo pod snadností úprav představuje jen úpravy měřené počtem řádků případně absenci nutnosti měnit schéma. Jenže snadnost úprav je něco víc – nejdřív totiž musíme nějak přijít na to, jaké řádky kódu a jak budeme měnit. A tenhle proces může být daleko zdlouhavější, než samotné napsání té pár řádkové úpravy. Je to podobné jako opravování chyb – samotná oprava chyby je často triviální, ale přijít na to, kde ta chyba je, to je skutečná práce.
Pokud je to důležité, tak lze samozřejmě udržovat dokumentaci, že jo.Jenže u relační databáze tu dokumentaci ani udržovat nemusíš, taková databáze je dokumentovaná sama sebou. Resp. jasně, že je hezčí, když má člověk aktuální (neaktuální je spíš na škodu) model v nějakém CASE nástroji, ale i když takový model nemá (buď se mu s ním nechtělo dělat nebo je zastaralý), máme jasnou představu o struktuře dat – už jen na základě názvů tabulek, sloupečků, jejich popisů a cizích klíčů – dále pak na základě primárních klíčů, datových typů atd. tohle jsou všechno deklarativní věci, které není potřeba dolovat ze zdrojáků, prostě koukneš a vidíš.
SQL je specializovaný jazyk, takže jako dokumentace je zřejmě o něco hodnotnější, ale pořád je to zdroják.Právě že ne – nikdo tě nenutí studovat kilometry skriptů obsahující
CREATE TABLE bla bla bla
. Místo toho se podíváš na jejich výsledek, běžící databázi (třeba testovací, vývojovou) a tam vidíš všechny ty tabulky a vazby, aniž bys musel louskat nějaký zdroják. Existují i nástroje pro analýzu těch DB a jejich vizualizaci, takže má pak člověk podobný pohled jako fyzický model v CASE nástroji. Co uvidím v běžící bezschémové databázi? AFAIK jen data, bez struktur, resp. každý kousek dat bude mít nějakou svoji strukturu. Nebo se z toho dá vydolovat nějaké zobecnění? Např. vyhledat záznamy stejného typu, stejných struktur a udělat z toho pohled na nějaké „třídy“ objektů. V relační DB jsou tyhle „třídy“ explicitně a předem definované – jako tabulky.
jak se chovat k dokumentové databázi relačním způsobemNejde o to, chovat se k ní relačním způsobem – jde o to získat přehled, jaká data máme. Protože když ten přehled nemáme, tak je to jen hnůj, se kterým se nedá pracovat. A pokud ten přehled musíme získávat čtením zdrojáku, tak je to velice nepříjemné a pracné, byť možné.
Čím dál víc se mi zamlouvá ta paralela s dynamicky typovanými jazykyDá se najít i paralela s WWW. Na webu je taky spousta dokumentů, rozházených všude možně po síti. Taky je to hnůj, který může zkoumat člověk (číst si www stránky), ale počítač mu nerozumí – úspěch je, když jsou označené nadpisy a odstavce, ale co představují ty dokumenty obsahově počítač netuší, drtivá většina webu není sémantická. Na webu to ale jinak nejde, resp. zlepšení (sémantika) přichází pomalu, takže se s tím musíme nějak poprat. Ale nevidím důvod proč si stejný chaos zanášet do své vlastní aplikace, kterou mám pod kontrolou a kde si strukturovanost a sémantiku můžu vynutit (což na webu nemůžu – nemůžu nařídit všem autorům www stránek, ať používají RDF nebo mikroformáty a pečlivě všechno označují).
BTW: „hnůj“ tu nemyslím jako urážku, ale prostě nestrukturovaná nesémantická data – typickým příkladem je webová stránka – může být hezká, může obsahovat užitečné informace, ale nemá předem danou strukturu (z hlediska sémantiky*), resp. každá stránka má nějakou svoji strukturu (to jsou ty různé verze dokumentů, „new“ a „old“ nastrkané v jedné databázi), a strojové zpracování je tak výrazně složitější než nad strukturovanými daty s předem daným schématem.
*) gramatiku na úrovni validního XHTML považuji za samozřejmost, ale to nás v tomhle případě nespasí, protože nevíme, že v <h1> se nachází název státu a ve třetím odstavci je jméno presidenta.
Lidi od dynamických jazyků postupem času vyvinuli celkem sofistikovaný testovací aparát
Kdyby radši vyvinuli pořádný typový systém, který by mohli používat normální programátoři v normálních aplikacích
To spouštění uživatelského kódu v rámci typového systému ze zápisku vedle o Perlu 6 je třeba docela pěkný nápad, nemyslíte?
Není to špatné, ale osobně bych preferoval, když by se na místech, kde to jde, místo běhových kontrol používaly kontroly statické -- nejlépe ve formě důkazů.
No a na hraní s typovými systémy jsou tu haskellisti, že jo. Je teda fakt, že Haskell je dneska asi v trochu lepším stavu než Perl 6
Mně by se třeba líbilo, když by se zkombinoval typový systém jazyků Disciple a Idris.
Jo, a nádavkem by mohli vyřešit problém zastaveníMyslíš tenhle? Nebo ten, v jehož řešení vystupuje
SIGKILL
a return true;
?
To je ten vtip. S relační databází je to nepředstavitelné.Viz:
Nemá smysl zavrhovat ani jedno ani druhé, každý druh databáze najde nějaké uplatnění. Ale asi by bylo dobré se řídit tím, jaká data máme na vstupu.Pokud je vstupem internet, resp. nekonečné množství www stránek, které jsou nesourodé, nesémantické atd. tak dá rozum, že si ty stránky nebudeme kopírovat do relační databáze a hledat v nich pomocí
WHERE html LIKE '%usa%president%'
.
Ale pokud jsou vstupem nějaké formuláře nebo jinak strukturovaná data, je to úplně jiné kafe. Osobně si myslím, že to nadšení kolem „nosql“ je přehnané a spousta lidí se k nim uchyluje jen proto, že se pořádně nikdy SQL nebyli schopní naučit. Trochu se obávám, že v rámci téhle módní vlny se „nosql“ databáze nasadí mnohde i tam, kam se nehodí (hodí jen na specifické případy). Ale to vlastně nevadí, aspoň pak pro nás bude víc práce, až se budou tyhle aplikace zase předělávat Pro nijak nestrukturovaná data Googlu je to s masivním paralelismem otázka maličkých zlomků sekundy.Ale výsledek je diametrálně jiný – výsledkem je odkaz na dokument, ve kterém se možná ta informace vyskytuje – nikoli ta informace jako taková, což by nám přišlo z relační DB. A masivní paralelismus a maličké zlomky sekundy? Tady je vidět, jak je zpracování nestrukturovaných dat náročné* – místo datacenter googlu mi na relační databázi stačí obyčejné PCčko, třeba i deset let staré. Jasně, objem zpracovaných dat je jiný, ale pokud by Google nebo WolframAlfa měli k dispozici velmi dobře strukturovaný a sémantický web, spotřebovali by mnohem méně výkonu a jejich výsledky by byly kvalitnější. *) ještě k tomu se neprohledávají data jako taková, ale jejich index.
Já bych řekl, že data obecně bývají nestrukturovanáCož je z velké části tím, že mnoho lidí ještě nepostřehlo, že na stole mají místo psacího stroje počítač – místo aby psali na papír a kopírák, to teď píší do Wordu, místo aby to dávali do šanonů ve skříni to dávají do složek na disku. Takovým lidem počítač prakticky nepomohl a využívají jen zlomek jeho možností. Je to ale jejich problém. Nestrukturovaná data jsou mor a potýká se s ním řada firem. Ale zpět k té tvorbě webů. Co takový elektronický obchod nebo redakční systém. Kolik dat v takové aplikaci je strukturovaných a kolik nestrukturovaných? Nestrukturovaný je třeba slovní popis výrobku nebo obsah článku. Ale ten zbytek?
a nebude to nahodou tim, ze svet (na urovni naseho rozliseni) je nestrukturovany? je jenom iluzi, ze vsechno se da nacpat do nejake predem znameho formatu... vzdycky me dokonale dokaze vytocit hlaska nejake urednice: ,,ale ja nevim, jak to zadat do pocitace''. typicky priklad... nedavno jsem se stehoval z US a musel jsem na nekolika mistech nahlasit zmenu adresy... v bance jsem stravil hodinu jenom proto, ze zenska nemela zpusob, jak zadat ceskou adresu do jejich systemu, ktery mel data hezky strukturovane na americke adresy. a to nebyla jedina situace... v jine DB to po me chtelo at vedle statu (CR) vyplnim jako povinny udaj i ,,provincii''... evidentne jejich DB mely dobre navrzenou strukturu, ktera ale vubec nevyhovovala realnym potrebam...Já bych řekl, že data obecně bývají nestrukturovanáCož je z velké části tím, že mnoho lidí ještě nepostřehlo, že na stole mají místo psacího stroje počítač
Hezké příklady, ale neukazují nedostatky relačních databází a předem daných schémat, ale chybu analýzy.ty priklady nemeli ukazovat nedostatky relacnich databazi... ale ukazat, ze ne vsechno ma predem znamou strukturu...
Nejedná se o nějaké nečekané změny, to, že existují i jiné země než USA je známý fakt a aplikace by s tím měla počítat.jo, jenomze ruzne zeme maji ruzne konvence, jak popsat adresu a jak ji zobrazit... a je nemozne podchytit vsechny mozne kombinace
ale ukazat, ze ne vsechno ma predem znamou strukturuTa struktura je předem známá. Resp. pokud v zadání máme, že budeme podporovat adresy různých zemí, nemůžeme klást příliš velká omezení, ty struktury budou volnější.
je nemozne podchytit vsechny mozne kombinaceMožné to je a běžně se i ta data ukládají do relačních databází. Už jsem adresu na pár nečeských webech vyplňoval a téměř vždy bez problémů – státy světa jsou obvykle jako číselník a zbytek nějaký
varchar
, tam se vejde všechno. Občas mají kraje/provincie své země jako číselník, ale pokud to nepsalo pako, tohle políčko není povinné, pokud nejsi z daného státu.
Ta struktura je předem známá. Resp. pokud v zadání máme, že budeme podporovat adresy různých zemí, nemůžeme klást příliš velká omezení, ty struktury budou volnější. ... státy světa jsou obvykle jako číselník a zbytek nějaký varchar, tam se vejde všechno.takze s SQL si muzu vybrat, ze adresa bude bud (1) struktura ktere neodpovida presne vsem pozadavkum (US adresa vs. adresy ze vsech statu sveta), (2) nejaky BLOB (varchar). a co kdyz budu v pripade (2) chtet vyhledat vsechny lidi, co bydli treba v texasu? je opravdu tak tezke priznat si, ze jsou situace, kdy SQL a relacni databaze s pevnou strukturou tabulek nejsou uplne nejlepsi reseni?
varchar
, tak jsem na úrovni nosql databáze – v tomto ohledu (můžu zadat libovolný kraj/provincii i z jiného státu), jinak jsem samozřejmě nad její úrovní, protože už při prvním pohledu na databázi je jasné, že tady máme nějakou entitu adresa
a ta obsahuje atributy stát
, město
, ulice
atd. – a nemusím kvůli tomu zkoumat data nebo zdrojový kód, abych zjistil tyhle základní informace.
IMHO nijak, protože zatímco v relační DB budu mít hnůj jen tam, kde je nutný (kraje/provincie u cizích států) v nerelační databázi budu mít hnůj všude (budou tam samé dvojice klíč-hodnota bez pevné struktury).bez fantazie to jde tezko... neprogramujes nahodou v jave? IMHO jedno z reseni je mit entitu adresa, ktera bude mit vic tvaru napr. ,,cz-adresa'' (majici atributy: ulice, cislo popisne/orientacni, mesto, psc, zeme) a pak treba ,,us-adresa: cislo popisne, ulice, apt/suit, mesto, zip, stat, zeme'' a pak treba obecna adresa: ,,radek1, radek2, radek3, zeme'' ... ano jde to udelat i v relacni db, ale neni to zrovna nejhezci... skutecnost, ze mas vic typu adres, musis resit v DB i v aplikaci... bez schematu ten problem resis jen v aplikaci
Pokud budu v relační tabulce řešit kraj nikoli odkazem na číselník krajů, ale jako varchar, ......nechapu k cemu se to vztahuje...
Hezké příklady, ale neukazují nedostatky relačních databází a předem daných schémat, ale chybu analýzy.To je právě ono - těch chyb analýzy je v reálné praxi až moc a v podstatě největší problém jaký v oblasti softwarového inženýrství existuje (a se kterým se již alespoň 20 let bojuje). Ne-SQL je prostě jenom jeden z další řady pokusů a zlepšení situace jako bylo OOP, agilní metodiky, dnes třeba funkcionální programování či dynamické jazyky. Osobně si nemyslím že by to byla nějak zvlášť úspěšná vlna, na většinu stávajících problémů je asi relační databáze lepší. Ale na tom vůbec nezáleží, jediné důležité je co ukáže praxe. A to ať si každý vyřeší sám, zda si pro svůj projekt zvolí správně.
To je právě ono - těch chyb analýzy je v reálné praxi až moc a v podstatě největší problém jaký v oblasti softwarového inženýrství existuje (a se kterým se již alespoň 20 let bojuje)obavam se, ze moc zpusobu, jak zlepsi kvalitu analyzy neni... a je spis potreba podivat se na zpusob vyvoje, ktery umozni efektivne reagovat na nedostatky (a omezene moznosti analyzy)... viz ony agilni metodiky nebo ,,dynamicke'' jazyky...
Osobně si nemyslím že by to byla nějak zvlášť úspěšná vlna, na většinu stávajících problémů je asi relační databáze lepší.relacni db jsou na spoustu veci dobre... ale treba u tech webovych aplikaci zacinam pochybovat a myslim, ze veci typu couchdb muzou pomoct prekonat nektere problemy... par let zpatky jsem byl deprimovany z toho, jak zakaznici neustale meni pozadavky a ovlivnen dynamickymi jazyky a hlavne schemem jsem si napsal hybrid mezi ORM a no-sql db (tehdy jsem ani nevedel, ze neco takoveho existuje)... a prekvapilo me, jak to zrychlilo vyvoj a udrzbu cele aplikace...
obavam se, ze moc zpusobu, jak zlepsi kvalitu analyzy neniA co kdyby analýzu nedělal ten, kdo neumí programovat, ale ten, kdo má analytické myšlení?
Nad relační databází zase řešíš hned dva jazyky zároveň
A to je problém? Běžně můžeš mít v aplikaci pět jazyků:
Je to moc? Bylo by lepší to psát všechno jedním jazykem? Kterým?
Map
a List
, takže je lze použít se syntakticým cukrem [name: "Ladicek", age: 27]
nebo ["sci-fi", "fantasy", "horor"]
. Ale v tom mi asi rozumíš, a máš svoje důvody, proč Groovy nepoužít.
Taky mi teda uniká to bezbolestné (vs. bolestné) mapování na objektySerializace a deserializace je velice snadné uložení a načtení objektu, asi to nejsnadnější.
Proč by se človek nemohl hrabat v datech uložených v bezschémové databázi "z jineho jazyka"?To bylo myšleno jako výhoda serializace do XML oproti serializaci do nějakého blobu. Ale připomněl jsi mi tím jednu věc, kterou jsem chtěl napsat už dřív. Databáze se schématem IMHO daleko líp podporuje vrstvenou architekturu. Typicky: data → aplikační logika → prezentační logika. Takže když dojdeš k tomu, že aplikace není už dost dobrá a chtěla by přepsat, můžeš si nechat databází a vyměníš jen tu vrstvu nad tím. Když je ale „schéma“ definované ve zdrojovém kódu aplikace…
Moje zkusenosti jsou, ze kazda vyrobni firma do 500 milionu kc (250 lidi, 80 pc) muze jet na systemu bez relacnich databaziA co třeba naše škola? Máme kolem 20 000 studentů + zaměstnanci + všichni bývalí uživatelé. Studijní systém běží samozřejmě nad relační databází, kupoval se na to Oracle za pěkných pár mega (IMHO spíš nepěkných). Systém se stará o veškerou studijní agendu (akorát účetnictví je zvlášť). Na tohle bys taky nasadil NoSQL nebo je to už za tou hranicí, kdy se systém dá ukočírovat bez jasného schématu a SQL? Kdybych to měl dělat já, tak Oracle bych si asi nevybral, ale bez relační databáze bych si takový systém nedokázal představit (resp. dokázal, ale ta představa by pak byla taková, že projekt dopadne blbě a asi se systém vůbec nespustí).
.cz
by se o tématu mělo mluvit víc, než se děje (pár článků nebo blogů jsem zaznamenal, ale bylo jich dost málo). Nepovažuje se za odborníka na dané téma, vlastně se nepovažuje za odborníka na žádné téma, ačkoliv o spoustě témat s oblibou odborně žvaní, ale tak nějak neviděl jinou možnost Zdá se mi že tvůj pohled je silně ovlivněn zkušenostmi s relačními databázemi a nejsi moc otevřen jinému přístupu...
To ani omylem. Já nejsem žádný SQL guru ani fanatik, od obého tu jsou jiní . Naopak bych velmi ocenil článek typu: "máme miliardu záznamů a takhle to děláme efektivněji než to skladovat v relační DB". Tenhle článek je typu, "tu miliardu záznamů máme sice pořád v DB, ale věci které tento konkrétní DB server neumí si děláme bokem".
Zkrátka z toho článku mám pocit, že změnou schématu či db serveru by dosáhli téhož mnohem efektivněji, přičemž nepochybuji o jejich odborných kvalitách.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.