Benchmark způsobů ukládání souborů do PostgreSQL

Před nějakou dobou prezentoval článek věnovaný různým způsobům ukládání souborů do PostgreSQL databáze, v jehož závěru jsem sliboval benchmark popisovaných variant ukládání. Sice to chvíli trvalo, ale benchmark je tu ...

Benchmark je celkem jednoduchý - je vygenerován zvolený počet souborů s velikostí náhodně zvolenou z daného intervalu. Poté následuje vlastní benchmark, spočívající v uložení všech vygenerovaných souborů do databáze, jejich postupném načtení a nakonec vymazání z DB. Přitom je měřen čas potřebný na každou z uvedených tří fází.

Testovány byly následující tři způsoby ukládání souborů:

  • obyčejný BYTEA sloupec - celý soubor uložen v jednom BYTEA sloupci, který je součástí vlastní tabulky
  • striped BYTEA - soubor je rozdělen na segmenty dané velikosti, a tyto segmenty jsou uloženy do samostatné tabulky
  • LOB - soubor je interně uložen obdobně jako "striped BYTEA" ale jedná se o funkcionalitu zabudovadou přímo do PostgreSQL, a díky tomu podporuje např. skutečný streaming apod.

Co se týká testovaných kombinací počet / velikost souborů, byly testovány celkem čtyři následující kombinace (počítané tak aby celkem daly cca 500MB):

jméno počet souborů min. velikost max. velikost celková velikost
velmi malé soubory 10000 10 kB 100 kB 537 MB
 malé soubory 1600 128 kB 512 kB 500 MB
 střední soubory 700 512 kB 1 MB 525 MB
 velké soubory 70 5 MB 10 MB 525 MB

Dva z testovaných způsobů ukládání umožňují ukládání nebo čtení dat po segmentech, konkrétně:

  • LOB - při čtení je možné stream číst pomocí bufferů různých velikostií
  • striped LOBu - soubory je možné při ukládání dělit na segmenty různých velikostí (a následně to pochopitelně hraje roli při čtení)

S ohledem na to jsou testováno více variant s různými velikostmi segmentů, konkrétně:

  • bytea - jediná varianta (nemá parametry)
  • LOB - čtení streamu pomocí bufferů 512B, 1kB, 2kB, ..., 128kB a 256kB
  • striped BYTEA - ukládání do segmentů 512B, 1kB, 2kB, ..., 128kB a 256kB

Několik důležitých poznámek

Hlavní část benchmarku je napsána v PHP, což souvisí s tím že se většinu menších webových projektů realizuji právě v tomto jazyce, takže právě benchmark napsaný v PHP pro mne dává nejlepší smysl. Nastavení PHP je víceméně standardní, ovšem s tím že kvůli ukládání velkých souborů do bytea sloupců byl zvýšen memory limit na 128 MB.

Použitá verze PostgreSQL byla 8.3.6 s víceméně standardním nastavením, tj. byly provedeny základní úpravy tak aby parametry odpovídaly například množství paměti (effective_cache, buffery, apod.) a podobně. Žádné speciální ladění pro tento benchmark neprobíhalo. Autovacuum démon byl ponechán zapnutý, ale byl nastaven poněkud agresivněji (nižší delay, vyšší cost limit). V případě zájmu je možné si konfigurační soubor stáhnout.

Prezentované výsledky byly naměřeny na mém domácím PC - AMD 64 X2 4400+, 2GB paměti, standardní SATA disk, Gentoo Linux (zkompilovaný pro 32bit). Na nabušeném serveru s výkonnějším HW (SCSI nebo SAS disky, lepší procesory, apod.) pochopitelně naměříte vyšší hodnoty, ale relace mezi výkonem jednotlivých způsobů ukládání zůstanou zachovány.

Soubory byly generovány do adresáře umístěného v paměti v ramfs filesystému, a to kvůli eliminaci vlivu načítání souborů z disku na benchmark. Soubory měly náhodný obsah, generovaný pomocí /dev/urandom.

Pro všechny benchmarky byla vždy použita stejná sada souborů daného typu, ale před každým benchmarkem (způsob uložení, jiná velikost segmentu) byla databáze vždy dropnuta a znovu vytvořena, a po načtení souborů do DB byl ručně spuštěn příkaz ANALYZE.

Všechny grafy uvedené v následující fázy zachycují počet vteřin potřebný k vykonání dané operace (zápis souborů do DB, jejich načtení a nakonec i smazání).

Velmi malé soubory

Při zápisu velmi malých souborů do DB jednoznačně vede použití LOBů, následované obyčejným BYTEA sloupcem. Striped BYTEA sloupce je nejpomalejší, ale s rostoucí délkou segmentu se rychle blíží BYTEA sloupci (v podstatě od 4kB je výkon srovnatelný s BYTEA sloupcem a od 8kB již měřitelný rozdíl neexistuje), což je způsobeno také malou velikostí souborů (max. 100kB) a tedy rychle klesajícím počtem segmentů.

Při čtení z databáze poněkud překvapivě velmi výrazně ztrácí řešení s LOBy (bez ohledu na velikost bufferu), zatímco BYTEA a striped BYTEA jsou v podstatě vyrovnané (opět platí že čím delší segment tím více se tato řešení blíží, aby od 4kB byla v podstatě ekvivalentní).

Při mazání souborů z databáze není mezi řešeními výrazný rozdíl - nejpomalejší je BYTEA, ale LOB je rychlejší jen o cca 10%, a striped BYTEA dosti "skáče" okolo LOBu.

Malé soubory

I v případě zápisu malých souborů (cca 128kB až 512kB) do DB jednoznačně vede použití LOBů, následované obyčejným BYTEA sloupcem, kterému ale od 4kB výrazně šlape na paty striped do BYTEA.

Čtení z databáze je ve srovnání s velmi malými soubory daleko vyrovnanější - s výjimkou velmi malých BYTEA segmentů (512B a 1kB) jsou řešení velmi vyrovnaná - nejlépe se jeví striped BYTEA se segmenty o velikosti 4kB až 64kB, následované BYTEA sloupcem. Výkon LOB řešení poměrně znatelně osciluje.

Mazání z databáze je opět velmi vyrovnané, s tím že nejrychlejší je BYTEA sloupec, LOB je o cca 20% pomalejší a striped BYTEA kolem nich osciluje - někdy je rychlejší, někdy pomalejší (v podstatě bez ohledu na velikost segmentu).

Středně velké soubory

V případě zápisu středně velkých souborů (cca 512kB až 1MB) se opakuje situace z předchozích dvou sekcí - opět celkem jasně vede použití LOBů, následované obyčejným BYTEA sloupcem, kterému se ale od 8kB celkem výrazně blíží striped BYTEA.

I u čtení z databáze se opakuje situace z předchozího odstavce - s výjimkou velmi malých BYTEA segmentů (512B a 1kB) jsou řešení dosti vyrovnaná - celkově se nejlépe jeví striped BYTEA  o velikosti 4kB až 64kB, následované BYTEA sloupcem a LOB řešeními (které tentokrát takřka vůbec neosciluje).

I mazání z databáze je opět velmi vyrovnané, s tím že nejrychlejší je BYTEA sloupec, LOB je o cca 20% pomalejší a striped BYTEA kolem nich osciluje - někdy je rychlejší, někdy pomalejší.

Velké soubory

I v případě zápisu velkých souborů (cca 5MB až 10MB) se opakuje situace z předchozích dvou sekcí - opět celkem jasně vede použití LOBů, následované obyčejným BYTEA sloupcem, kterému se ale od 8kB celkem výrazně blíží striped BYTEA.

I u čtení z databáze se opakuje situace z předchozích odstavců - s výjimkou velmi malých BYTEA segmentů (512B a 1kB) jsou řešení dosti vyrovnaná - celkově se nejlépe jeví striped BYTEA o velikosti 4kB až 64kB, následované BYTEA sloupcem a LOB řešeními.

I mazání z databáze je opět velmi vyrovnané, s tím že nejrychlejší je BYTEA sloupec, LOB je o cca 10% pomalejší a striped BYTEA kolem nich osciluje - někdy je rychlejší, někdy pomalejší.

Shrnutí

Z předchozích odstavců lze udělat několik následujících závěrů:

  • Mazání je ve všech případech naprosto srovnatelné - žádné řešení nijak výrazně nevybočuje. Pokud potřebujete řešení s rychlejším mazáním, můžete použít "lazy delete" - namísto smazání pouze označit a smazat později (například v noci z cronu apod.).
  • Co se týká zápisu, jednoznačně nejrychlejší je LOB, s uctivým odstupem (50% až 100%) následovaný BYTEA sloupcem. Striped BYTEA je pro segmenty nad 4kB srovnatelné s BYTEA sloupci, přičemž je výrazně méně paměťově náročné.
  • Při čtení dat se nejlépe osvědčilo striped BYTEA o velikostech mezi 8kB a 32kB, následované prostým BYTEA sloupcem, a nakonec LOB.

Závěry jsou celkem jednoduché - pokud potřebujete ukládat jen relativně malé soubory (tj. takové při jejichž escapování nedojde k vyčerpání memory limitu v PHP), bude asi nejjednodušší použít obyčejný BYTEA sloupec.

V případě větších souborů je to složitější - pokud zásadní roli hraje rychlost jejich vkládání, je asi lepší využití LOBů. Naopak pokud potřebujete brát v potaz zejména čtení, udržení integrity DB (přeci jen LOBy neumožňují cizí klíče apod.), může pro vás být výhodnější striped BYTEA.

Soubory ke stažení

  • skripty pro benchmark - Předem upozorňuji že tyto skripty nejsou příliš (tj. rozuměj "vůbec") připravené na spouštění mimo můj počítač - jsou v nich cesty a přihlašovací údaje natvrdo, apod. Takže pro ilustraci jsou ideální, ale pro zprovoznění se v nich budete muset "trochu" (tj. rozuměj "hodně") povrtat.
  • výsledky benchmarku - Výsledky benchmarku (výpisy z PHP skriptu a také log z dstat).

 

Komentáře

K tomuto článku zatím žádné komentáře neexistují (nebo čekají na schválení).

Nový komentář

Všechny komentáře podléhají schválení - mezi odesláním komentáře a jeho zobrazením na této stránce tedy může být prodleva. Vyplníte-li e-mailovou adresu, budete o schválení či neschválení komentáře informováni.

V titulku ani v textu nejsou povoleny HTML tagy - budou automaticky odstraněny. Odstavec ukončíte prázdným řádkem.

(nepovinné)