Nagy mennyiségű adat szűrése + lapozgatás?
Próbálom röviden, de így is hosszú lesz :)
Nagy tömegű adatból kell lekérdezést csinálni, lapokra osztva az eredményt.
A gond ott kezdődik, hogy regex alapú szűrést akarok végezni az adatokon.
Postgres esetében ez nem gond, de ha az a vágyam, hogy a program ne legyen driver függő, akkor azt hiszem, az adatbázis szerverek spéci szolgáltatásaira nem számíthatok.
Amíg mindent intézhetek adatbázis oldalon, addig no problem, a megcélzott keretrendszer (flask+sqlachemy) nyújt lapozós szolgáltatást egy paginate nevű függvény formájában.
De mi a bánatot lehet csinálni, ha olyan válogatást kell végezni, amire az adatbázis nem képes? A meglévő 5-6 millió sor betöltése kifekteti a szervert és a klienst is, részben timeout, részben out of memory képében.
Van erre valami megszokott, elfogadott algoritmus, hogy lehessen könnyen, gyorsan lapozgatni a találatok közt és ne bolonduljon meg az oldalszámozás?
Mert az még O.K., hogy az első lapot megjelenítem úgy, hogy addig olvasom a sorokat, amíg be nem jön egy oldalnyi a szűrésre illeszkedő sor.
De az utolsó (tehát nem a 123. oldalra, hanem általánosságban az utolsó) oldalra csak úgy tudnék lépni, ha végigolvasom a teljes táblát, ami iszonyat lassú.
Caching nem igazán jöhet szóba, mert ahhoz is kellene előbb egy teljes olvasás és ugyanott tartok.
De akkor hogy?
■ Nagy tömegű adatból kell lekérdezést csinálni, lapokra osztva az eredményt.
A gond ott kezdődik, hogy regex alapú szűrést akarok végezni az adatokon.
Postgres esetében ez nem gond, de ha az a vágyam, hogy a program ne legyen driver függő, akkor azt hiszem, az adatbázis szerverek spéci szolgáltatásaira nem számíthatok.
Amíg mindent intézhetek adatbázis oldalon, addig no problem, a megcélzott keretrendszer (flask+sqlachemy) nyújt lapozós szolgáltatást egy paginate nevű függvény formájában.
De mi a bánatot lehet csinálni, ha olyan válogatást kell végezni, amire az adatbázis nem képes? A meglévő 5-6 millió sor betöltése kifekteti a szervert és a klienst is, részben timeout, részben out of memory képében.
Van erre valami megszokott, elfogadott algoritmus, hogy lehessen könnyen, gyorsan lapozgatni a találatok közt és ne bolonduljon meg az oldalszámozás?
Mert az még O.K., hogy az első lapot megjelenítem úgy, hogy addig olvasom a sorokat, amíg be nem jön egy oldalnyi a szűrésre illeszkedő sor.
De az utolsó (tehát nem a 123. oldalra, hanem általánosságban az utolsó) oldalra csak úgy tudnék lépni, ha végigolvasom a teljes táblát, ami iszonyat lassú.
Caching nem igazán jöhet szóba, mert ahhoz is kellene előbb egy teljes olvasás és ugyanott tartok.
De akkor hogy?
Adatbázisnál erre van
Egyszer én is kellett ilyent
Nem így értettem, hanem
Asszem,félreértesz: nincs fix
Az indexen láttam egy durva negatív példát: a törölt kommentek is ott vannak az adatbázisban, csak nem jelennek meg.
Ennek eredménye, hogy régi topic-ok, rengeteg törölt hozzászólással úgy jelennek meg, hogy az utolsó oldalak üresek, de sorszámot azért kapnak. :)
Ha a regex user input, akkor
A kulturált megoldás
Megtehetem, hogy letöltöm az eredményt memóriába, és attól kezdve már van miből lapszámot generálni.
Csak annyi memória a világon nincs rossz esetben :)
Végső megoldás lehet az is, hogy ha elég a session indulásakor rendelkezésre álló adat, hogy elküldöm háttérbe a lekérdezést és készítek belőle egy ideiglenes táblát.
Mondjuk ez már valahol a cache kategória.
A kérdés egyébként onnan jött, hogy a logjaimon ismerkedtem az ORM csodáival és sikerült ráengedni egy SyslogTable.query.all() lekérdezést, amitől pár percre lefagyott a notebookom :D Ebből kiindulva találtam rá a paginate()-re, és akkor kezdtem töprengeni, hogy egy komolyabb adatbázisból hogy lehetne normális, lapozós lekérdezést elkövetni egy előre nem rögzíthető lekérdezés esetén (pl usertől érkező regex).
ui: a korábbi hozzászólásomat kissé elírtam... nem 50-100 tételre gondoltam, hanem arra, hogy ennyit kap elsőre az arcába a sokmillióból, aztán ebből válogathat pl. regex mintával.
Lapozás
Ez is szerverfüggő, de ha azonosak a szűrési feltételek, akkor pontosan meghatározható a lapok száma (ezt rontja el az index az üres lapoknál), és tudod, hogy hányadik lap az utolsó.
Hátránya, hogy kétszer futtatod majdnem ugyanazt a query-t, viszont ez akár előny is lehet: a modernebb adatbázisok ezt már elég jól cache-elik kvázi automatikusan.
Teljesítmény szempontjából jobb megoldás, amit megpedzettél már, hogy előzetes lekérés alapján bizonyos részeket temp táblába tolsz, lehetőleg memóriában.
Ha szét tudod bontani kisebb részekre a regex-et, akkor pl az egyes részeknek megfelelő Id-kat szóród így ki kis táblákba, végül ezekkel egy ügyes JOIN a fő táblán.
Ilyenkor mindig érdemes mérni a teljesítményt, hogy melyik megoldás a gyorsabb / jobb, mert (db szervertől függően) bele lehet futni még az eredetinél rosszabb / lassabb teljesítménybe is.
(Regex-el még nem csináltam ilyet, de nagy db-n, usertől érkező szűrőfeltételekkel igen, hogy a rengeteg JOIN miatt milliárdos nagyságrendű rekord keletkezett _volna_, ha nem bontjuk szét és nem csinálunk temp táblát hozzá.)
Kicsit összezavarodtam (nem
Végülis az említett paginate() függvény megteszi ezt (select count(), majd select) helyettem valahogyan, ráadásul adatbázis típustól függetlenül. Franc a szenilitásba... Megint nem jut eszembe, hogy ez hol és miért nem volt jó.
Szerintem valamit nagyon túlgondoltam: ha valahol mélyen a listában járok és a user átírja, szűkíti a keresést, akkor egyszerűen visszadobom az első oldalra, oszt jónapot.
Nekem kicsit úgy tűnik, hogy
Egyébként ha már szóba került, cloudon kívül van bármi, ahol tudnék nodejs-t futtatni anélkül, hogy a rendszergazdai tevékenységet el kéne látnom? Néztem a dotrollt, de az CGI, ami rohadtul nem nodejs. Átgondoltam, és soha többet nem akarok én már PHP-zni vagy ilyen thread based architecture-t használni. Egyszerűen nem szeretem.
Nem, ez nem az "építéshez"
Ja hát vannak korlátai az
Logikus
Annyira nem. (csak példa)
Végülis, ha a rendezés ár
Ez csak egy példa volt, ami