sql >> Databáze >  >> RDS >> PostgreSQL

Django + Postgres + Velké časové řady

Pokud správně rozumím vašim myšlenkám, uvažujete o uložení časové řady v PostgreSQL, jeden záznam časové řady v jednom databázovém řádku. Nedělejte to.

Na jedné straně je problém teoretický. Relační databáze (a myslím, že většina databází) jsou založeny na předpokladu nezávislosti řádků, zatímco záznamy časové řady jsou fyzicky uspořádány. Databázové indexy samozřejmě poskytují určité pořadí databázových tabulek, ale toto pořadí má za cíl urychlit vyhledávání nebo prezentovat výsledky v abecedním nebo jiném pořadí; neimplikuje to žádný přirozený význam tohoto řádu. Bez ohledu na to, jak si je objednáte, je každý zákazník nezávislý na ostatních zákaznících a nákup každého zákazníka je nezávislý na jeho dalších nákupech, i když je můžete získat úplně chronologicky, abyste vytvořili historii nákupů zákazníka. Vzájemná závislost záznamů časových řad je mnohem silnější, což činí relační databáze nevhodnými.

V praxi to znamená, že místo na disku, které zabírá tabulka a její indexy, bude obrovské (možná 20x větší než ukládání časových řad do souborů) a čtení časových řad z databáze bude velmi pomalé, něco jako objednávka pomalejší než ukládání do souborů. Také vám nepřinese žádnou důležitou výhodu. Pravděpodobně nikdy nepoložíte dotaz „poskytněte mi všechny záznamy časových řad, jejichž hodnota je větší než X“. Pokud někdy budete potřebovat takový dotaz, budete potřebovat i sakra jinou analýzu, pro kterou relační databáze nebyla navržena, takže celou časovou řadu stejně načtete do nějakého objektu.

Každá časová řada by tedy měla být uložena jako soubor. Může to být buď soubor v systému souborů, nebo blob v databázi. Navzdory skutečnosti, že jsem implementoval to druhé, věřím, že první je lepší; v Django bych napsal něco takového:

class Timeseries(models.model):
    name = models.CharField(max_length=50)
    time_step = models.ForeignKey(...)
    other_metadata = models.Whatever(...)
    data = models.FileField(...)

Pomocí FileField zmenší vaši databázi a usnadní vytváření přírůstkových záloh vašeho systému. Bude také snazší získat řezy hledáním v souboru, což je pravděpodobně nemožné nebo obtížné s blobem.

Nyní, jaký druh souboru? Doporučil bych vám podívat se na pandy. Je to pythonovská knihovna pro matematickou analýzu, která má podporu pro časové řady a měla by mít také způsob, jak ukládat časové řady do souborů.

Výše jsem odkazoval na svou knihovnu, kterou vám nedoporučuji používat; jednak nedělá to co chcete (nezvládne zrnitost jemnější než minutu a má jiné nedostatky) a jednak je zastaralý - psal jsem to před pandami a hodlám to převést v budoucnu používat pandy. Existuje kniha „Python pro analýzu dat“ od autora pand, kterou považuji za neocenitelnou.

Aktualizace (2016): Je tu také InfluxDB. Nikdy jsem to nepoužil, a proto nemám žádný názor, ale rozhodně je to něco, co musíte prozkoumat, pokud vás zajímá, jak ukládat časové řady.

Aktualizace (2020-02-07): Existuje také TimescaleDB, rozšíření PostgreSQL.

Aktualizace (2020-08-07): Změnili jsme (opět) náš software tak, aby ukládal data do databáze pomocí TimescaleDB. Už jsme zběhlí v PostgreSQL a bylo snadné se naučit nějakou TimescaleDB. Nejdůležitější konkrétní výhodou je, že můžeme zadávat dotazy typu „najít všechna místa, kde během 24 hodin v roce 2019 napršelo>50 mm deště“, což by bylo velmi obtížné při ukládání dat do plochých souborů. Další výhodou jsou kontroly integrity – v průběhu let jsme měli několik časových řad s duplicitními řádky kvůli malým chybám tu a tam. Nevýhody jsou také významné. Využívá 10krát více místa na disku. Možná kvůli tomu budeme muset změnit naši politiku zálohování PostgreSQL. Je to pomalejší. Načtení časové řady s 300 000 záznamy trvá možná jednu sekundu. To bylo předtím okamžitě. Potřebovali jsme implementovat ukládání do mezipaměti pro načítání časových řad, což dříve nebylo potřeba.



  1. Jak LTRIM() funguje v MariaDB

  2. MySql zobrazuje výkon

  3. Změna definice TYPU v Oracle 21c

  4. ZOBRAZIT TABULKY v MariaDB