nagy mennyiségű adat cachelése

Fórumok

Nagy mennyiségű adatot (több millió rekord) szeretnék cahe-elni és erre keresek valami jó módszert.

A fejlesztési környezet MySql és Java EE 7 (GlassFish).

Van egy kereskedelmi rendszer ahol termékeket értékesítenek. A termékek mozgása egy táblában található. Vannak különböző mozgásnemek melyek növelhetik, csökkenthetik a készletet vagy nincs készlet hatásuk.
Pl:
FORGALOM
ID_CIKK
DATUM
MENNYISEG
EGYSEGAR

Szükség van kimutatások készítésére egy adott időszak forgalmáról. Mennyi volt az adott időszak elején a nyitó készlet, mennyi volt a növekedés, csökkenés, a forgalom valamilyen módon számított fogyasztói és beszerzési árakon (többféle módon lehet számolni ez lényegtelen most a probléma szempontjából)

Jelenleg tervek szerint úgy működne a dolog, hogy egy éjszaki job leválogatja, hogy egy adott terméknek adott napon volt-e bármilyen mozgása és azt beleteszi egy cache táblába és a kimutatások már ebből a táblából dolgoznának.

Pl: ha egy adott termékből volt egy nap 300 vevőnek eladás egy 1 beszállítótól beszerzés, akkor az a cache táblában egy soron fog megjelenni,
pl. reszelt tejszínhab, csökkenés 1300 db, növekedés 200 db, adott napi mozgás -1100 db. Ezen kívül még kiszámolom hogy mennyi volt az aznapi nyitó készlet, záró készlet, illetve készlet értéket.

Ez mind szép és jó, addig amíg nem akarja a listákat úgy lekérni, hogy benne legyen a mai dátum, mert úgy a job éjszaka fut és csak az előző napig vannak benne az adatok.

Most én négy módszert látok a probléma megoldására:

1;
Ha listákat úgy készítem el, hogy ha a mi dátum is benne van a szűrő paraméterekben akkor egyrészt dolgozok a cache táblából, a mai adatokat pedig a többi táblából szedem össze. Így bonyolult lesz a kód, másrészt ha bármilyen változtatást kell eszközölni az üzleti logikában akkor azt minden kimutatáson át kell vezetni.

2;
Futhat egy job is amely x percenként az újonnan keletkezett adatokkal frissíti a cache táblát, de itt megint fennáll a veszélye annak hogy nem kap releváns adatot. pl. 15 perces a frissítési ciklus és az utolsó óta történt valami nagyobb készletmozgás.

3;
Ha a felhasználó kér egy listát és a szűrés a mai napra is vonatkozik, csak abban az esetben frissítem a cache táblát az újonnan keletkezett adatokkal. Talán ezt tűnik a legjobb módszernek. Ha még nem volt az adott tételből mozgás aznap, akkor bele insertálom a cache táblába, ha már volt mozgás akkor csak updatelem a rekordot az új értékkel. Csak itt meg akkor lehet gond ha sok user kezd el kimutatásokat készíteni. Egyszerre rengetegszer lesz lekérve az aznapi forgalom és insertálva/updatelve a cache táblába.

4;
a 2. és 3. kombinációja.

Melyik módszert érdemes használni, vagy van e erre esetleg valami jó design pattern.

Hozzászólások

A "több millió rekord" önmagában még nem tényező, ha a táblák jól vannak szervezve és az indexek száma és tartalma jól van balanszírozva és a támogató memóriacache is megkapta a szükséges tuningot.

Cache (vagy MQT - https://community.toadworld.com/platforms/ibmdb2/w/wiki/7223.materializ…) táblát csak abban az esetben használnék (pontosan a felsorolt aggályok miatt), ha a fentiek valamiért nem teljesíthetők - ez a ritkább eset.

Ha fennáll a veszélye a riport szükségtelen klikkelgetésének, vagy időzítővel meg kell oldani, hogy csak x másodpercenként legyen startolható, vagy flagelni, hogy a következő csak akkor, ha az előző már nem fut, vagy adott pillanatban csak n-szeri futását engedélyezni.

Egy lehetőség, hogy van a termék táblában egy aktuális mennyiség oszlop, és a mozgásoknak van egy másik táblája (termék, dátum, delta) oszlopokkal. Utóbbi táblából termék és dátum szerint csoportosítva, deltát összegezve kijönnek a napi mozgások, egy termék aktuális készlével összevetve pedig látod, hogy melyik nap mennyi volt a készlet (ezt már kódból számolnám, ha megvan a többi adat SQL-ből). Nem gondolom, hogy pár millió sor esetén ez kezelhetetlen lenne. De van az úgy, hogy a denormalizált adatszerkezet a célrevezető, és a mozgások táblában lenne egy oszlop a mozgás utáni aktuális készlettel. Csak arra kell figyelni, hogy ezek a megoldások lockolással járnak, viszont nem mondtad, hogy egetverő lenne az írások gyakorisága. A módszer előnye, hogy az élő táblában ott van minden adat, ami a lekérdezéshez kell.

Ha így lassú a query mert pl. szar a hardver, akkor a következő ötlet egy materialized view vagy hasonló (ezt hívod cache táblának, de az a lényeg, hogy egy jó RDBMS ezt adja neked ingyen, nem neked kell megírni). Ezt akár óránként vagy sűrűbben is lehet automatizáltan frissítgetni. Ha ez nem elég friss, akkor a view-ból kérdezed le a korábbi adatokat és melléteszed a view frissítése utáni változásokat (de ez csak akkor lesz jó, ha utóbbi halmazba kevés adat kerül).

Ilyen kis adatmennyiségnél én nem feltétlenül mennék bele bonyolultabb kódolásokba, memcached használatába vagy ilyesmi. De lenne ötletem arra is.

Ja egy hasonló ötlet: a termékmozgás táblában legyenek egyedi és aggregált sorok termékenként. Lenne egy háttérfolyamat, ami időről időre fog egy csomó egyedi mozgást, összegzi őket, elmenti az összeget, és archiválja az egyedi sorokat. Ezt így könnyű sql-ből lekérdezni és tuti gyors lesz. (Ugyanezt csinálja minden time series adatbázis: régebbi adatok időbeli felbontása csökken, de a séma ugyanaz marad.)

Kimondottan erre jók a triggerek. Minden táblába insert-elés után lefuttat egy insert or update-et az aggregált adatokra is és csókolom. A teljes logika a db szerveren belül marad.

Vizsgára felkészülés végett keresek "kidobásra" szánt menedzselhető Cisco switch-eket és routereket, leginkább Pest és Bács-Kiskun megye területén.

Igen, ezért is javasoltam többször is. Ha már a db szerver biztosítja azt, hogy automatikusan aggregáljon, akkor érdemes kihasználni, mivel így a kódot elég egy helyen karbantartani, és így frontend oldalon nem kell több különböző kódbázisba belenyúlni, ha éppen az alkalmazás olyan, hogy pl van neki webes, desktop és valamilyen egyéb felülete is.

Vizsgára felkészülés végett keresek "kidobásra" szánt menedzselhető Cisco switch-eket és routereket, leginkább Pest és Bács-Kiskun megye területén.

A MySQL-nel van memory táblatípusa, illetve van memcached is. Mindenképp az appod fogja tudni, hogy minek kell cache-ben lennie.

Szóval egyik helyen történik valami, amit egy másik helyen is fel kellene dolgozni, lehetőleg kis késleltetéssel. Akkor ha történik csökkenés vagy növekedés küldesz egy eventet az iránnyal, a mennyiséggel, meg az új összmennyiséggel, és ezeket az eventeket figyeli egy listener. A listener meg updateli az adott napi rekordot, így mindig friss.

Nekem ket megoldas jut hirtelen az eszembe:

1. Egy tablaban nyomonkovetni az arumozgast. Pl.
Ido (unix epoc), termek-id, mennyiseg, tranzakcio-tipus (eladas/vetel)

Definialni egy ido ablakot es az ennel regebbi adatokat arhivalni/torolni etc

2. Az arumozgast elasticsearchben vagy time-based db-ben tarolni. Elasticsearch eseteben meg a vizualis megjelenites is egyszeru.

Szerk: time-based az time series akart volna lenni. Elnezest.

Én a helyedben tuti csinálnék egy triggert az adattáblára. Új sor beszúrásakor pedig a triggerrel frissíteném a cache tábla adatait. Ezzel a megoldással a cache csak akkor frissül, amikor kell, a db-re nézve pedig live adatok lennének benne.

Vizsgára felkészülés végett keresek "kidobásra" szánt menedzselhető Cisco switch-eket és routereket, leginkább Pest és Bács-Kiskun megye területén.

A "több millió" rekord az semmi, bocs.

Javaslom, hogy először is csináld meg a reportot generáló SQL-t úgy, hogy a live adatokból dolgozik (valami ilyet kérnek, nem?), tuningold kicsit, s nézd meg, mennyi idő alatt készül el.
Ha napi report, akkor még 5 percnyi futásidő is oké lehet, de ezt neked kell tudnod :-)

Jól megválaszott indexekkel és táblaszerkezettel több _milliárd_ soros táblákból joinolgatva, aggregálgatva is lehet 38 sec alatt reportot generálni. Szal mindent lehet.

Maga az irány azért lehet jó, hogy ne dolgoztassuk halálra szegény sql szervert. Megfelelően indexelve valószínűleg az aggregálás tényleg gyorsan lefuthat egy pár millió rekordos táblán, de ha már az elején okosan csinálja, akkor később nem kell a sok száz milliós/milliárdos rekordszámnál azon aggódni, hogy hogyan gyorsítson rajta.

Vizsgára felkészülés végett keresek "kidobásra" szánt menedzselhető Cisco switch-eket és routereket, leginkább Pest és Bács-Kiskun megye területén.

Ez a rendszer már működik, vagy még tervezés alatt van? Mérések alapján gondolod, hogy ez a szűk keresztmetszet, vagy csak tipp?