it-swarm-eu.dev

Ukládání vs výpočet agregovaných hodnot

Existují nějaké pokyny nebo pravidla, která určují, kdy ukládat agregované hodnoty a kdy je vypočítat za běhu?

Předpokládejme například, že mám widgety, které uživatelé mohou hodnotit (viz schéma níže). Při každém zobrazení widgetu jsem mohl vypočítat průměrné uživatelské hodnocení z tabulky Ratings. Jinak bych mohl uložit průměrné hodnocení do tabulky Widget. To by mi ušetřilo potřebu vypočítat hodnocení pokaždé, když zobrazuji widget, ale pak bych musel přepočítat průměrné hodnocení pokaždé, když uživatel ohodnotil widget.

Ratings       Widgets
---------     -------
widget_id     widget_id
user_id       name              
rating        avg_rating  <--- The column in question
100
BenV

To záleží. Předběžný výpočet agregovaných hodnot klade větší zátěž na zápisy, jejich odvozování ztěžuje čtení

Pokud často přistupujete k odvozené hodnotě, je předběžný výpočet platným krokem k normalizaci. V tomto případě však doporučuji použít materializované zobrazení (pohled zapisovaný na disk, spojený spouští s nadřazenými tabulkami). Zhmotněný pohled je navržen tak, aby ukládal často žádaná, ale zdlouhavě odvozitelná data, a je užitečný pro vysoký počet zápisů a nízký počet čtení.

Ve scénáři s vysokým zápisem a vysokým čtením uvažujte o úkolu na pozadí, který napodobuje účinky materializovaného pohledu, ale v méně než reálném čase. To bude představovat „dost dobrý“ průměr při zachování výkonu zápisu a čtení.

Za žádných okolností byste neměli zacházet s odvozeným sloupcem jako s „normálním“ sloupcem: ujistěte se, že data uvedená v zobrazení „Widgety“ jsou přítomná kdekoli v tabulce, takže celé Tuple lze odvodit z jakýchkoli procesů, které vydáváte. Tato otázka je také silně specifická pro databázi (a verzi databáze), takže doporučuji testování výkonu agregátu (s příslušnými indexy) oproti normálním souborům dat a materializovanému pohledu.

60

Jak často je třeba vypočítat/zobrazit hodnoty relativní k tomu, jak často se podkladová čísla mění/aktualizují.

Pokud tedy máte web s 10k přístupy denně, který zobrazuje hodnotu, která se změní pouze jednou za hodinu, vypočítal bych ji, když se změní základní hodnoty (může to být spoušť databáze, cokoli).

Pokud máte nějaký nástroj, který vám pomůže podívat se na statistiky, kde se statistika mění o sekundu, ale máte přístup pouze tři lidé, kteří se na to dívají jen několikrát denně, je pravděpodobnější, že vypočítám to za běhu. (ledaže to trvá několik minut, než se spočítá, že mít zastaralá data na prvním místě není velký problém ... a můj šéf mi říká, abych každou hodinu generoval věc z cronu, takže nemá počkat, až se na to chce podívat.)

11
Joe

Použijte tabulku StaleWidgets jako frontu „neplatných“ (přepočítaných) widgetů. Použijte jinou podprocesovou (asynchronní) úlohu, která může tyto hodnoty přepočítat. Období nebo okamžik přepočtu závisí na systémových požadavcích:

  • právě číst,
  • na konci měsíce
  • pro některé uživatele na začátku dne
  • ...
4
garik

Navrhuji, aby se kalkulovalo za běhu, pokud by kalkulace nebyla příliš těžkopádná a v případě, že máte složitou kalkulaci a častou aktualizaci, ale ne to, že čte frequnet, než můžete ukládat vypočtená data a mít navíc sloupec (bool), který bude ukládat, zda je třeba přepočítat, nebo ne . např. nastavte tento sloupec na true, kdykoli by měl být přepočet proveden, ale nedělejte přepočet a když provedete přepočet, nastavte tento sloupec na hodnotu false (bude to představovat vypočtená hodnota nejnovější a nikoli zastaralá).

Tímto způsobem nemusíte přepočítávat pokaždé, budete počítat pouze tehdy, když musíte číst a přepočítat hodnotu sloupce je pravda. Tímto způsobem ušetříte spoustu přepočtu.

2
techExplorer

Obzvláště v tomto případě existuje odlišné řešení, kde nemusíte přidávat všechna hodnocení a vydělit je celkem, abyste našli průměr. Místo toho můžete mít jiné pole, které obsahuje součet recenzí, takže pokaždé, když přidáte hodnocení, vypočítáte nový průměr pomocí (avg_rating × total + new_rating)/total, je to mnohem rychlejší než agregace a snižuje čtení disku, protože nemusí mít přístup ke všem hodnotám. Podobná řešení mohou platit i pro jiné případy.

Nevýhodou je, že se nejedná o kyselou transakci, takže byste mohli skončit zastaralým hodnocením. Ale přesto to můžete vyřešit pomocí triggerů v databázi. Druhým problémem je, že databáze již není normalizována, ale nebojte se denormalizovat data výměnou za výkon.

2
Adrian Martinez