Ideální embedded databáze
by měla splňovat několik náročných požadavků. Měla by:
- být rychlá.
- mít bug free kód.
- nevytvářet zbytečně velké soubory.
- mít rozumné API – nejlépe ndbm komatibilní.
- být odolná při práci s poškozenými daty. Pokud by uměla navíc recovery dat, tak by to bylo výborné.
- mít dobře vytunované default nastavení. Téměř nikdo ho nebude měnit.
- být použitelná i pro komerční projekty. Tzn. ne GPL-poison, pokud možno ne LGPL kvůli nutnosti dynamického linkování. Nejlépe s BSD, X11 nebo s public domain licencí.
- mít dostatečně širokou uživatelskou základnu, aby se vychytaly chyby.
- mít rozumnou velikost kódu – vhodné pro statické linkování.
- být přenositelná na Windows a Unix.
- být použitelná z několika programovacích jazyků.
- být stabilizovaná, ne na pochodu. Nikdo nemá zájem pořád upravovat své programy podle momentálních změn v API a konvertovat data. Neustálé vydávání nových verzí taktéž nebudí důvěru.
Koho si vybrat
Databází implementujících diskové haštabulky jsou mraky. Snad každý programátor, který tuto úlohu řešil, si napsal tu svou, pochopitelně také se svým zcela novým API. Ve FreeBSD portech v sekci databáze jsem napočítal 17 kusů, přičemž mohu vyjmenovat přibližně stejné množství databází, které v portech nejsou.
Ačkoliv jsou těchto databází mraky, nejčastěji se používá jen pár kousků, a na ty jsem se zaměřil. Po pár úvahách jsem se rozhodl pro jednoduchý klíč – zaměřím se na ty databáze, které mám nainstalované. Tak automaticky vyberu ty nejpoužívanější.
Soutěžící
1.
Jméno: Berkeley DB 1.85
Důvod kandidatury: Standardní součást (g)libc.
Domov: FTP Archiv starých verzí na www.sleepycat.com
API: NDBM, DB1
Licence: BSD
Prog. jazyky: C
2.
Jméno: Berkeley DB 4.1.25
Důvod kandidatury: Naistalovaná jako závislost PHP4
Domov: www.sleepycat.com
Licence: Free pro použití v open source projektech, jinak hustá komerce.
API: NDBM, DB1, DB4
Prog. jazyky: C, C++, Java, TCL, RPC
3.
Jméno: Trivial database 1.0.6
Důvod kandidatury: Naistalovaná jako součást Samby
Domov: sourceforge.net/projects/tdb
Licence: GPL poison druhého stupně
Prog. jazyky: C
API: vlastní, podobné NDBM s rozdílným předáváním parametrů
4.
Jméno: GNU database manager 1.8.3
Důvod kandidatury: Naistalovaná jako backend GNU-Netu
Domov: www.gnu.org/software/gdbm
Licence: GPL poison prvního stupně
API: DBM, NDBM a GDBM – odvozené z NDBM
Prog. jazyky: C
5.
Jméno: Quick database manager 1.8.8
Důvod kandidatury: Před časem naistalovaná za účelem testování
Domov: qdbm.sourceforge.net
Licence: LGPL dll deployer 2.1
API: NDBM, GDBM, vlastní depot, curia, villa, odeum
Prog. jazyky: C, Ruby, C++, Java, Perl
Zajímavé je, že nikdo nedělá DB1 kompatibilní API.
6.
Jméno: tiny cdb
Důvod kandidatury: Součást Eximu
Domov: www.corpit.ru/mjt/tinycdb.html
Licence: Public domain
API: CDB
Databáze byla napsána z důvodu příliš restriktivní licence u originálu. Kromě zrychlení a zmenšení přináší i pár věcí navíc.
7.
Jméno: Pure DB
Důvod kandidatury: Součást Pure FTPD
Domov: www.pureftpd.org/puredb
Licence: BSD
API: Vlastní
Také tato databáze byla napsána kvůli nespokojenosti s licencí CDB. Datový formát byl však velice jemně pozměněn (poloviční hlavička, big endian), a tak není s CDB datově kompatibilní.
API
Databáze poskytují své služby pomocí exportovaného API.
Abych se lépe seznámil s jednotlivými nativními API testovacích databází, napsal jsem testovací příklady s jeho využitím. Ukázalo se, že návrh API není rozhodně silnou stránkou mnoha programátorů. Když pominu otázku, proč za každou cenu vymýšlet ke své databázi nekompatibilní API, úplně by stačilo vzít NDBM standard a případné dvě funkce navíc k němu přidat, málokterý programátor si uvědomil, že API musí být hlavně jednoduché a mělo by následovat zásadu nejmenšího překvapení.
Provedl jsem také test za účelem zjištění overheadu NDBM-kompatibilního API wrapperu. Na Pentiu 100 rok výroby 1995, což byl nejpomalejší počítač, na který jsem se mohl nalogovat, jsem nezjistil žádné měřitelné zpomalení. To zcela popřelo častý agument proti wrapper API – zpomalení programu. To by snad bylo měřitelné až na 20 let starém hardwaru. Na mém 20 let starém hardwaru – ZX-Spectrum, Sord, a MSX – tyto produkty neběží.
Wrapper API se při programování databází využívají docela často. Jedním z nejznámějších pro jazyk C je embedded SQL, které značně šetří čas programátora a je navíc přenositelné. Jako příklad špatně navrženého API u SQL databází lze uvést Oracle Call Interface, které rozhodně není programátor-friendly, podívejte se např. na Oracle driver pro dspam. Naopak jako příklad dobře navrženého API může posloužit nativní API PostgreSQL – driver je zhruba poloviční.
Subjektivní hodnocení jednotlivých API
1. DB1
DB1 API je pokus o imitaci objektově orientovaného API v neobjektově orientovaném programovacím jazyce, jakým jazyk C je, což působí trochu úsměvným dojmem. Autorům se tato koncepce však zalíbila natolik, že od ní neupustili ani v dalších dílech DB ságy. Pokud vám tato koncepce nevadí, nedá se API jinak nic vytknout.
2. DB4
API zestárlo o 10 let, nabralo trochu na složitosti, avšak základní koncept zůstal stejný jako u DB1. Některé části by se sice daly vyřešit elegantněji, ale celkový dojem z API to nekazí. Jako major annoyance hodnotím nutnost programovat stylem „před použitím protřepat“.
DBT key, value; memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value));
3. TDB
API TDB je netypické tím, že nepředává datové struktury přes pointer, ale hodnotou, což se v C moc nevidí. Autor dostal kladné body za to, že nechal u struktury TDB_DATA NDBM kompatibilní názvy položek. Mezi námi, měl ponechat i názvy funkcí a své k nim přidat.
TDB_DATA key,value; ... tdb_store(db,key,value,TDB_INSERT)
4. GDBM
GDBM API se liší od NDBM mírně semanticky, na což se při portaci směrem gdbm-ndbm musí dávat pozor. Viz minulý díl.
5. QDBM
K tomuto API mám jednu dost podstatnou námitku, která ho řadí jednoznačně na poslední místo. Všechna ostatní API respektují v C zažité pravidlo: při úspěchu se vrací 0, jinak < 0. QDBM vrací při úspěchu hodnotu 1.
6. tiny CDB
Zde nemám žádné připomínky – je CDB kompatibilní.
7. Pure DB
Toto API je zajímavé dvěma věcmi, které se týkají ne zrovna standardní dynamické alokace paměti:
- funkci open musíte dodat pointer na již naalokovanou řídící strukturu. Běžně se to tak nedělá.
- po funkci close musíte ještě zavolat funkci pro free, pričemž není možné řídící strukturu zrecyklovat pro další open bez předchozího zavolání free.
V příštím dílu už najdete nějaká ta čísla. Pokud toužíte po srovnávacím benchmarku již nyní, podívejte se na qdbm projekt. Ačkoliv se QDBM řadí mezi nejrychlejší databáze i v mém testu, rozhodně to není s takovým náskokem jako v jejich benchmarku.