Použít nízkoúrovňový jazyk dává určitou výhodu, v tom máte určitě pravdu. Naštěstí je možné tyto přístupy kombinovat - příkladem může být třeba QuestDB, která, byť je napsaná v Javě, pro "horká místa" používá kód v Céčku a kombinuje oba přístupy. Je to také jedna z alternativ, kterou bychom se do budoucna mohli vydat.
Jinak s performance benchmarky je to vždycky velmi ošidné. Velmi záleží na komplexitě dotazů, velikosti a struktuře dotazovaného datasetu, kombinaci read / write operací - tj. toho, jak je výkonnostní test koncipován a proti jakým datům běží. Proto jsou pro nás nakonec nejdůležitější benchmarky ty, které měří na produkčních datasetech a přehrávají záznam dotazů, které se reálně na daném řešení uskutečnily.
Nějaké benchmarky vznikly už ve výzkumné fázi projektu. V rámci seriálu bych chtěl ještě nabídnout aktualizované benchmarky z prvních nasazení databáze v produkčním prostředí (ale už bez porovnání s alternativními implementacemi, protože funkcionálně jsme už mnohem dál). Viz. historie projektu.
Tenhle problém řešíme tak, že u produktu máme referenci na jiné produkty. Na úrovni reference (vazby) potom určujeme jestli se jedná o "náhradní díl" / "alternativní produkt" / "také koupili" a následně to přes tuto referenci načítáme. Tuto situaci máme i v demo datasetu, pro který jsem naznačil ukázkovém GraphQL dotazu (stačí jen odklepnout varování, že dotaz pochází z neznámého zdroje a dotaz klidně spusťte - demo je v read-only režimu a ničemu tam není možné ublížit).
Plnění těchto referencí je samozřejmě už na aplikaci, která ta data naplní z nějakého zdrojového systému (typicky nějaká forma ERP, e-shop administrace nebo z výstupu strojového učení).
Větší detaily ohledně dotazování dat mám připravené v třetím dílu série.
In-memory může být ale tak trochu problém, když ty data začnou růst. Krásný příklad je třeba elastic search. Cute databáze až do doby, kdy člověk začne platit mega měsíčně jen za servery, které se většinu času stejně flákají...
Chtěl by to benchmarky. Třeba zníměná QuestDB má JIT pro kompilaci dotazů, takže je hodně rychlá, ale JIT má třeba i Tableau, takže to není něco nového a v této oblasti jde momentálně o boom.
Problém ale opravdu nastává, když ty data jsou obrovské, aneb když se začne čekat na data. Co pak... nejlepší je ty data kompresovat, a pak začíná úplně jiný boj...
Tím chci říct, že navrhnout in-memory databázi není až takový problém, reálný engineering jde vidět až když ty data se do RAMky prostě nevlezou.
U in-memory to riziko skutečně existuje, jak píšete a stejně tak s Vámi souhlasím, že velká data jsou skutečně mnohem náročnější na zkrocení. My se orientujeme ale na doménu, kde je situace trochu specifická. evitaDB je vyhledávací index nad aktuálními daty pro katalogová řešení - neřešíme fulltext index nad logy ani time-series data, které mají potenciál nabobtnat do obřích rozměrů. Zároveň databáze by se neměla "většinu času flákat" - pokud by to tak bylo, Vaše katalogové řešení nikdo moc nenavštěvuje a tím pádem tuhle databázi pravděpodobně nepotřebujete. evitaDB je OLTP, nikoliv OLAP a to ještě se zaměřením na "read-heavy" scénáře.
My se snažíme vyřešit problém, kdy na omezené sadě dat, která je už ale dostatečně veliká, potřebujeme vyřizovat velké množství dotazů s nízkou latencí. Tj. řešíme náš problém, na který jsme nenašli uspokojivé řešení - a nejde pouze o výkonnost, ale řadu dalších aspektů (viz. další díly seriálu).
Naše testovací sady obsahovaly cca 100 tisíc entit (prodejních produktů), což vyžadovalo cca 10GB dat paměti, ale to samozřejmě odpovídá použitému datovému schématu. Jiná schémata se 100 tisíci entitami mohou zabírat více i méně paměti podle počtu indexů a dat, podle kterých se dá vyhledávat.
Tahle databáze cílí na eshopy - a to ještě jednu konkrétní část, takže tam by problém s velikostí být neměl. 100-300GB servery nejsou už extra exotika, a pro vytížený shop se vyplatí. Občas jsem u svých zákazníků viděl, jak pracně navrhují určitá řešení nad Postgresem, a říkal jsem si, že jednoduchá vlastní inmemory databáze pro jejich daný use-case by byla řádově rychlejší. Pokud se vám potřebné struktury vejdou a udrží v RAM, tak nic nemůže být rychlejší. Trochu mám problém s tou Javou, ale i ta se nakonec zkompiluje. Výhodou inmemory databází je, že je možné je napsat poměrně snadno, a můžete si navrhnout speciál pro svůj specifický use case - speciální operace na grafech, stromech nebo maticích. A pokud jsou data immutable, tak nemusíte tolik řešit konzistenci, souběhy.
Ve výsledku větší zatíženější řešení jsou mix technologií, a funguje je to nejlépe. Předpokladem je realistický pohled na každou technologii, znát výhody, nevýhody, limity.
plny souhlas, a hlavne kdyz misto RAM se pouzije NVRAM
https://en.wikipedia.org/wiki/Non-volatile_random-access_memory
pak neni treba ani zadne rychle SSD
25. 1. 2024, 16:46 editováno autorem komentáře
Aby nedošlo k mýlce - databáze je sice in-memory, ale data standardně ukládá na disk, takže při restartu o žádná data nepřicházíte. In-memory je v tom smyslu, že má v RAM všechny vyhledávací indexy - tj. k vyhodnocení dotazu není třeba seek na disku. Pokud si v rámci dotazu zažádáte o další data, která v indexech nejsou, protože se podle nich nevyhledává / netřídí, tak k přístupu na disk dochází. Ale to už je řádově mnohem menší množství fetchů, protože se už jen vyzvednou data z konkrétních pozic na disku.
Rádi bychom si našli čas na experimentování s CRaC, což by nám mohlo výrazně pomoci s obnovením větší instance databáze zpět do paměti (např. v budoucnosti i na replikách). Aktuálně probíhá jen cold start s postupným načtením indexů z binárních souborů do paměti.
"Občas jsem u svých zákazníků viděl, jak pracně navrhují určitá řešení nad Postgresem, a říkal jsem si, že jednoduchá vlastní inmemory databáze pro jejich daný use-case by byla řádově rychlejší"
Hloupá otázka, ale to je tím, že zrovna tuhle fíčuru (tj. držet si data v paměti) Postgres náhodou neumí, nebo je tam nějakej principiélní problém v architektuře těch databází?
Rozhodně nejsem PostgreSQL expert - ale v rámci našeho výkonnostního testování jsme měli pronajatou VPS se 128GB RAM (g-32vcpu-128gb na DO), kde se pohodlně celý disk vešel do paměti. Linux se chová tak, že pokud má dostatek volné paměti, tak si do ní ukládá data načtená z disku, takže po zahřátí by teoreticky PostgreSQL vůbec neměla fyzicky chodit na disk. Přesto byla řádově pomalejší, jak naše in-memory implementace.
Samozřejmě lze namítat, jestli byl návrh DB optimální a jestli jsme databázi zkonfigurovali správně tak, abychom z ní vytáhli co nejvíc. Ale to můžete posoudit sami - zdrojové kódy jsou veřejné.
Tam spíš půjde o to, jak budete mít nakonfigurované JDBC. Jinak z hlediska konfigurace Pg půjde jen o konfiguraci shared_buffers a možná asynchronního commitu. Posuzovat to nebudu, aby to mělo hlavu a patu, tak bych to musel odzkoušet na nějakém rozumném hw, a pár dní se tomu věnovat, což se mi fakt nechce :-).
Je tam několik principiálních problémů:
a) U klasické databáze jsou data na disku v jiném formátu než v paměti, takže když data načítáte, tak neustále musíte dělat konverze. Klasické relační databáze jsou navržené tak, aby mohli nějak fungovat s minimem paměti. Indexy nejsou navržené, aby měly co nejlepší výkon, ale aby se daly serializovat, případně aby se s nimi dalo pracovat, i když se vám vejde do RAM jen relativně malá část, a pořád to ještě bude funkční. Tohle celé u inmemory databází odpodá (za tu cenu, že pokud se vám data nevejdou do RAM, tak inmemory db nefungují nebo mají tragický výkon).
b) Relační databáze jsou většinou generické (nejsou optimalizované pro nějakou konkrétní úlohu) a jsou to interprety - interpret výrazů, interpret prováděcích plánů, atd. Inmemory databáze tak generické nejsou, mají menší sadu operací, která je zkompilovaná (alespoň větší část).
c) SQL optimalizátor předpokládá relační model, předpokládá denormalizovanou databázi, předpokládá určité chování statistik nad daty. Pokud něco z toho nemáte - jdete proti relačnímu modelu - např. použitím EAV, tak extra výkon mít nebudete.
d) SQL optimalizátor má určitou režii plus protokol. To je vidět u extrémně krátkých rychlých dotazů. Pokud nemáte generickou optimalizaci, nedokážete optimalizovat síťovou komunikaci, tak máte brutální overhead, který se projeví u krátkých extrémně častých dotazů (typicky benchmark). U Postgresu je dobré použít socket, prepared statements. Navíc JDBC je dost těžkotonážní interface - předpokládám, že pro přístup s Javy byl použit. To se dá redukovat uloženými procedurami, ale ne všichni tuhle technologii znají. Dovedu si představit, že to co dělá inmemory databáze, bych mohl dosáhnout v Cčkové extenzi Postgresu (ale ne všechno). Ale pro klasického programátora bude jednodušší si napsat vlastní inmemory db v Javě (a použije řadu hotových knihoven, komponent) než napsat Cčkovou extenzi pro Postgres.
Postgres, pokud máte dost paměti, tak data bude držet v cache datových stránek. Je tam i extenze pg_prewarm, abyste se tato cache rychle zahřála. Problém je, jako u všech klasických databází, že jsou tato data ve formátu v kterém jsou na disku. Když s nimi chcete pracovat, tak je musíte rozbalit, zkonvertovat a tyto konvertovaná data jsou časově omezená na max jeden dotaz, jednu operaci - a jinak to nejde. U klasických databází předpokládáte, že se vám data nevejdou do paměti. Vždy by šlo něco vymyslet, ale pokud nechcete aby vám db lagovala, tak není co moc vymýšlet. Ty klasické databáze nejsou navržené tak, aby vám v nějakých úlohách dávaly nejlepší výkon, ale jsou navržené tak, aby vám ve všech úlohách, které nejdou proti relačnímu modelu, dávaly vždy použitelný výkon. Navrhují se pesimisticky, nikoliv optimalisticky. U inmemory db je to pravý opak.
Plus máte nějakou režii s garancemi konzistence, s implementací zámků. Inmemory db mohou používat techniky, které jsou jednodušší, rychlejší - mohou používat podobný model jako SQLite. To klasické databáze nemohou - dotazy tam trvají delší dobu, běžně dochází k souběhu, a s jednoduchými řešeními by to ve více uživatelském režimu (máte víc zapisujících procesů) mělo tragický výkon (což je např. vlastnost SQLite).
Nějaký vývoj směrem k tomu, co dělají inmemory db, je třeba i u Postgresu (u jiných db to nesleduji), např. https://www.orioledata.com/ nicméně obecný názor je, že klasická databáze nemá suplovat inmemory databázi. Cílí to někam jinam, má to jinak uložená data, tudíž i jiné vlastnosti
Obecně u benchmarků různých technologií je několik problémů - první, že se občas porovnává neporovnatelné, druhý, že se porovnává pouze jeden use case, a třetí - že dost často autoři testů mají expertní znalost pouze jedné technologie, ale už pak jim chybí expertní znalost těch dalších technologií. Plus samozřejmě, že může být zadání, které nějaké technologii prostě sedět nebude.
Jednak si dovoluju pochybovat o tom, ze nejaky hej nebo pockej navrhne databazi lepe, nez jak je navrzena libovolna univerzalni databaze.
Dal, kazda svepravna databaze si v ram primarne drzi prave ta data, ktera pouziva. A pokud to ma i fungovat, tak se ocekava, ze cachehit bude vysoko nad 98%. Tudiz ve skutecnosti je v ramce vse, co se pouziva.
Pro specifické use case může i průměrně dobrý programátor napsat výkonnější inmemory db. Když se dělá analytika, tak agregace nad pamětí v C++ bude minimálně o řád až dva rychlejší než super rychlá relační db. Nejde jen o ten cache hit - ale jde i o to, kolik operací musíte s daty udělat, abyste je mohl používat. Dneska už dost často není brzdou IO, ale CPU.
OPRAVA - tam jsem napsal blbost
c) SQL optimalizátor předpokládá relační model, předpokládá denormalizovanou databázi, předpokládá určité chování statistik nad daty. Pokud něco z toho nemáte - jdete proti relačnímu modelu - např. použitím EAV, tak extra výkon mít nebudete.
Spravne by melo byt SQL optimalizator predpoklada normalizovanou databazi. - nejak po ranu mi to ujelo.
Díky moc za tento názor, velmi věrně kopíruje naše úvahy. Valná většina výpočtů je realizována pomocí množinových operací nad komprimovanými "maticemi" čísel, pro hierarchické vyhledávání máme index ve formě acyklického grafu - takže jste se trefil poměrně přesně.
Zároveň ale chceme mít některé vlastnosti blízké relačním databázím - máme podporu pro transakce a SNAPSHOT izolaci v duchu MVCC, dokážeme ověřovat konzistenci (tam kde to vývojář bude chtít) a budeme mít i celkem jemně nastavitelnou detekci konfliktů u souběžných transakcí.
O tom bych chtěl psát v některém z pozdějších dílů seriálu.
Limity databáze samozřejmě má a snažíme se v tomto být upřímní. evitaDB vidíme jen jako rychlý vyhledávací sekundární index. Na pozadí vždy předpokládáme využití některé z relačních databází. Stejně tak nedoporučujeme ukládat data jen do evitaDB, ale vždy je mít v nějaké primární databázi s vysokými garancemi. Objednávky, košíky, uživatele máme i my takové relační databázi - ale tato data mají úplně jiné potřeby a jiný životní cyklus jak "katalogová data".
Tady plati: "Vy mate Big data? A muzu je videt?" Resil jsem offloading for FullText search z Oracle do Elasticu. E-shop s 10M+ objednavek denne vygeneroval do 100GB dat (se zachovanim 4 mesicu retence).
Kapacita HW roste, a skutecne dulezita data jsou dnes vlastne hodne mala.
Jedna vec je davat do Elasticu logy ze serveru, a jina je indexovat jen adresy kam mate dorucit nejake zbozi.
26. 1. 2024, 11:20 editováno autorem komentáře
Co třeba 10 PB?
100GB je opravdu nic. Navíc 100GB by se dalo asi i hezky zkompresovat a pořád docílit průchod třeba 2-5GB/s na jádro podle komprese a datového formátu, takže i brute-force query bez indexů by na nějakém 64 core Epicu trval třeba půl sekundy. Ale asi ne s Elasticem, který nemá v podstatě žádné optimalizace a i blbá distance query se dá napsat 20x rychlej.
Aktuální verze je single node. V současné době vylepšujeme práci s transakcemi a zavedení write-ahead-logu, na kterém v blízké budoucnosti postavíme replikaci v clusteru. Letos bychom chtěli mít prototyp pro H/A řešení v K8S v režimu single master, multiple replicas. Repliky si budou v reálném čase z master node stahovat WAL s logickými operacemi, které následně přehrají na svých datech a tím se budou udržovat v syncu. Celé to stavíme na principu CDC, které bude k dispozici i k aplikačnímu použití. Sharding prozatím nezvažujeme.
Jinými slovy - tuhle funkcionalitu potřebujeme mít i pro vlastní potřeby, takže na ní aktivně pracujeme.
25. 1. 2024, 21:15 editováno autorem komentáře
Oni mají mnohem větší záběr, takže co se týká jádra tolik zase ne. Jejich counter typy jsou u nás ve formě ApplyDeltaAttributeMutation, která by nám měla umožňovat např. bezpečně aktualizovat stavy na skladě aniž bychom se museli bát konfliktů z paralelních zápisů. Naše Java API se má podobný přístup jako jejich API. Zajímavé jsou "time-travel" funkce - i když pro nás to není primární use-case, tak pro účely nějakého auditu, to je zajímavá vlastnost.
Jejich studio a dokumentační portál jsme zkoumali celkem pečlivě a když to porovnáte, tak uvidíte řadu podobných prvků.
Teď vyšlo celkem zajímavé nezávislé ověření tvrzení autorů RavenDB ohledně marketovaných vlastností transakcí od Jepsena a celkem dost tuto databázi strhali.
31. 1. 2024, 20:27 editováno autorem komentáře
Držím palce, při vývoji.
Pro mě je potěšující, že podobné cestičky jsem prošlapával v Pythonu před 20 roky, kdy jsem jako "one man show" vyvíjel aplikaci pro autoservisy a prodejce autodílů. Výchozí sada cca 2,5 mil. produktů, stovky výrobců, desítky dodavatelů, nekonečný proud ceníků...
Podkladová databáze byla MySQL s cca 40 tabulkami + několika tabulkami postavenými atributově a záměrně porušujícími všechny normalizační formy, aby to zachránily, jinak by těch tabulek byly stovky.
In-memory znamenalo vejít se do pár GB RAM, takže žonglování s tím, co tam pro jakou fázi zpracování dat držet.
Výkon HW z dnešního pohledu komický, pro urychlení načítání dat z DB vyšla nejlépe serializace do .temp souborů s hlídáním, kdy je nutné je zahodit a sestavovat znovu z DB.
Nebylo Alchemy, tak pomohla vlastní vrstva objektově-relačního mapování, nebyla ani CSV knihovna, které by uměla pořádně UTF8, takže vlastní zpracování, nebylo Pandas, tak pěkně vlastní knihovna pro práci s dvourozměrnými poli,...
Se ážitky s hrůzami co byly ve vstupních datech od polských dodavatelů bych mohl mohl strašit psychology dodnes.
Ale když se to po půl roce intenzivního kódění podařilo uschopnit , tak to co se jim ve Visual Basicu zpracovávalo 3 dny v kuse, tak na to najednou stačilo 10 minut. Takže zrychlení cca 400%.
Dalsi databaze? Databazovych vnitrnosti jsem mel uz tolik, ze je asi lepsi pokracovat v pustu :-)
Reknu tedy jen (nevyvazene) optimistickou cast. Mate dobry clanek i diskuzi. Hlavne za dojem z webu vas musim pochvalit! Ten ma svetovou uroven. Java je dobra volba. Mate sanci s tim uspet. Preji hodne stesti!
BTW: Kde myslite ze budou eshopy za pet let?