Ukládání souborů do DB

Na základě vlastních zkušeností technika (nikoliv programátora), zabývající se převážně ukládáním dat (systémy souborů a databáze), jsem sepsal několik ne/souvisejících poznámek o přístupu ukládání dat. Cílem je spíše otevřít diskusi a najít další argumenty. Snad ne flame.

Přístup k datům

Každý větší program, pokud to není jen jednoduchý filter zpracovávající data ze stdin s výstupem na stdout, potřebuje pracovat s persistentním úložištěm dat. Pro webové aplikace je to dnes typicky databáze (ať již SQL, nebo jakákoliv jiná, na tuto úvahu to nemá vliv) a zároveň systém souborů.

Tento dualismus vede na několik problémům, kterých se dotknu v dalších bodech. Co se týče přístupu k datům, tak čím více aplikace používá různých typů úložišť, tím větší úsilí musí programátor vynaložit (a tím větší náchylnost k chybám). Přístup k databázi, přístup k disku — tolik pro příklad. Je jich více. Pokud by data byla na jednom místě, aplikace by s nimi mohla pracovat jedním způsobem. Je v celku jedno, které je to místo. Pokud už aplikace vyžaduje ke svému běhu databázi (což neplatí vždy), je tímto jedním místem právě databáze. Pokud stačí disk, může být tímto jedním místem disk. Ale, tam hrozí nebezpečí, čtěte dále.

Množství souborů na disku

Dostáváme se k prvnímu problému, které programátoři aplikací ukládající data na disk musejí řešit (dříve nebo později). Tím je počet souborů.

Počet souborů na systému souborů, v adresáři, je omezen. Nikoliv direktivou z Bruselu, ale algoritmy toho kterého systému. Což si mnoho lidí zprvu neuvědomuje. Strop není tvrdý, jen při větším počtu souborů začne být daný systém souborů pomalejší a pomalejší. Zkušenosti ukazují, že toto číslo je pro systémy typu ext3 na jednom 7200rpm disku někde kolem stovek tisíc souborů. Pro systém XFS potom jednotky milionů. Potom je vytvoření dalšího souborů velmi pomalé. Zdá se, že moderní BTRFS je na tom lépe, ale ani ten nezvládne větší počty (desítky a stovky milionů).

Má to své důvody. Systémy souborů jsou navržené na typické použití s ohledem na maximální bezpečnost dat a na rychlost pro toto typické použití. Typické použití systému souborů nejsou stovky milionů malých souborů na disku. Uložit je tam můžete, ale při nejbližším fsck zapláčete. A uvidíte, kam vás vývojáři toho kterého systému souborů pošlou. Ano, do databáze.

Tato vlastnost potom vede některé programátory aplikací k tomu, že vymýšlejí různé způsoby, jak sice uložit soubory na disk, ale zase aby jich nebylo tak moc. A to je cesta do pekel. (Ani si to uvědomují, tak vlastně píší program, kterému lze říkat databáze.)

Většinou selhávají. Vývojáři objevují  znovu a znovu různě šišaté kolo a jejich programy pak soubory ukládají buď do adresářového stromu (squid, maildir, opera mail, gallery2 a stovky dalších) a nebo vymýšlí různé jiné způsoby uložení dat (archivace více souborů, o kterých si programátor myslí, že patří k sobě, do jednoho archivu) a to jen proto, aby se vyhnuli příliš vysokému počtu souborů.

Tato činnost nijak nesouvisí s daty ani s logikou aplikace a zbytečně programátora zdržuje a vede k chybám. A co je nejhorší, v praxi to potom vůbec nefunguje.

Databáze jsou na druhou stranu a na rozdíl od systémů souborů přímo navrženy na ukládání mnoha položek (existují a používají se databázové systémy s miliardami záznamů a velikostech v petabajtech). Počet položek v DB nás prakticky nezajímá, cílem je vytvořit dobré DB schéma. Vývojář tedy může uložit data aplikace přímo do databáze (se kterou již stejně pracuje) a nemusí se starat o způsob jejich uložení. Databáze to udělá lépe.

Rychlost

Souborové systémy selhávají při práci s mnoha soubory. Důvod je jednoduchý. Souborový system neví, který další soubor bude aplikace potřebovat a neexistuje API, jak by to aplikace mohla systému sdělit. Aplikace samotná to nemusí vědět. Proto zde neexistuje žádná readahead cache pro dopředné načítání souborů.

Co naopak existuje a dobře funguje, je readahead cache pro jeden soubor. Operační systém se snaží číst další bloky souboru ještě před samotným požadavkem z aplikace. Toto čtení probíhá sekvenčně, pokud se cache netrefí, není to taková tragédie.

Tím jsme se dotkli dalšího tématu. Systém souborů se snaží seč může udržovat soubory v jednom celku. Důvod je jasný. Zatímco sekvenční čtení dnešních disků dosahuje rychlostí přes 100MB/s, tak náhodné čtení (po 4kB blocích) jde rychlostí cca 0.5MB/s (200x nižší). Tedy, ať chceme nebo ne, jeden velký soubor se bude číst typicky rychlostí sekvenčního čtení, zatímco stejný objem malých souborů (o velikosti 4kB) se bude číst výrazně déle (až 200x déle). Asi si řeknete, že se ty soubory mohou číst tak jak jsou za sebou. Bohužel, ani na toto neexistuje API. Nelze OS předat seznam souborů k přečtení a i samotné zjistění „polohy“ souboru na disky vyžaduje další diskové operace.

Jednotné zálohování

Jako technik můžu pouze ocenit, pokud aplikace má všechny své informace na jednom místě. Pokud aplikace používá databázi, je výhra, pokud tam má všechna data. Pochopitelně kromě connection stringu. Mám bohaté zkušenosti s přenosy webových aplikací mezi servery a není nic horšího, než přenášet mnoho úložišť.

Dalším problémem je konzistence záloh. DB se zálohuje v transakci (viz další bod) a tato záloha je tedy konzistentní.  Souborový systém transakce neumožnuje a během zálohy se mění pod rukama. Tento problém řeší snapshoty (snapshot je zmražená němněnná podoba systému souborů — záloha snapshotu je tak konzistentní pro daný čas). Snapshoty umí vrstva LVM, ovšem nakládání s nimi je poměrně složité, a také moderní souborové systémy, jako například ZFS nebo již zmíněný BRTFS. Ten druhý je ovšem ve vývoji.

I kdybychom měli zálohu DB pomocí transakce a zálohu systému souborů pomocí snapshotů, tak záloha nemusí být konzistentní. Nelze začít transakci a snapshot v jeden okamžik (prakticky by to znamenalo přerušit činnost databázového serveru a souborového serveru a po té začít novou transakci  a udělat snapshot – v produkčním prostředí nemyslitelné).

Závěr

Věci nejsou černobílé. Mnoho zde nastíněných problémů se v praxi úspěšně řeší. Například nic tak nezrychlí souborový server, než paměť. Je samozřejmně otázkou, zda je levnější pořídit k 600GB SAS poli 128GB RAM, nebo upravit aplikaci. Ta ramka se dá využít i jinak. Upravená aplikace taky.

Stejně tak s nástupem SSD odpadá nutnost úzkostlivě řešit defragmentaci a počty malých souborů. Postupně se stírá rozdíl mezi sekvenčním a náhodným přístupem. Na nových diskových jednotkých s IOPS v milionech lze náhodným přístupem číst rychlostmi 4GB/s.

Příspěvek byl publikován v rubrice Databáze, Názory, PostgreSQL. Můžete si uložit jeho odkaz mezi své oblíbené záložky.

4 komentáře: Ukládání souborů do DB

  1. lzap napsal:

    brusel rules :-)

    Souhlas, na druhou misku vah bych ale zase dal svoji zkusenost. A to seekovani v blobech. Ne kazda databaze to podporuje a nekdy (vicestrankovy tiff) je to proste a jednoduse potreba. Takze ve vyjimecnych pripadech si dokazu predstavit vyjimku. Naposled si vybavuji kolegu v roce 1999 jak strasne nadaval u seekovani v db oracle. Ale treba jsou dneska uz veci jinak. Lepsi. :-)

  2. Pingback: Ukládání souborů do DB, odkazy a doplnění | Heronovo

  3. Pingback: Statistika stahování stránek II | Heronovo

Komentáře nejsou povoleny.