Zadejte hledaný výraz...

Sledování změn, efektivní ukládání do DB

Bacon
verified
rating uzivatele
(2 hodnocení)
24. 10. 2011 23:37:26
Dobrý večer,
chtěl bych se zeptat, jak by se nejlépe mělo řešit, když mám web, na kterém je cca 200 řádků, které chci scrapovat.
Každý řádek obsahuje boss_name a boss_status, ten nabývá hodnot boss_alive / boss_dead. Periodicky by se měl web kontrolovat (cca každou minutu) a:
  • pokud se hodnota boss_status změní (boss_alive -> boss_dead nebo boss_dead -> boss_alive), měl by se zapsat čas, ve který tato událost nastala a zapsat aktuální stav
  • pokud se hodnota boss_status nezmění, nemělo by se provádět nic
Zajímalo by mě, jak se toto řeší, protože první, co mě napadlo, bylo prostě pokaždé vzít a uložit všech 200 řádků a pak si jen vytáhnout poslední hodnotu boss_status pro každé boss_name. Což je ale dost neefektivní a databáze by se asi nafoukla do obřích rozměrů brzo.
Takže to chce asi dvě tabulky, jedna bude obsahovat ID a boss_name a druhá bude obsahovat boss_id, boss_status, timestamp.
Budu rád, když mě někdo nakopne ve dvou věcech:
  • Jak efektivně porovnávat minulý stav (uložený v databázi) se stavem na webu
  • Jak efektivně zaznamenávat změny stavů (včetně času)
Předem díky :)
24. 10. 2011 23:37:26
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690643
Michal Haták
verified
rating uzivatele
(1 hodnocení)
24. 10. 2011 23:55:25
imo pokazde musis nacist(minimalne do pameti) tech 200 radku, nechapu presne problematiku, respektive konkretni priklad(scrapovat ?), ale urcite se da vybrat jen podledni radek, ten porovnat se zaznamem v db a pripadne zapsat
k poslednim dvema otazkam:
zaznamenavani casu urcite pomoci timestampu
na porovnavani bych zkusil "==" (no offense)
zkus priblizit problematiku, uvest priklad :)
24. 10. 2011 23:55:25
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690642
hm
verified
rating uzivatele
(20 hodnocení)
24. 10. 2011 23:57:55
stejne jako twista uplne enchapu co vlasten delas, ceho tim chces docilit, neuvedl jsi zadny poradny priklad ani popis... zkus se rozepsat krok po kroku nebo alespon pozadovanou fci a priklad k tomu... ted jsem z tveho popisu zmateny a nemuzu poradit...
24. 10. 2011 23:57:55
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690641
Bacon
verified
rating uzivatele
(2 hodnocení)
25. 10. 2011 00:10:39
OK, asi je to jasné jen mně a tím pádem jsem to nedostatečně popsal... Mám tuto stránku: http://l2s.onlinegamers.cz/rb
Chci z ní v určitých intervalech (1 - 2 minuty cronem) načítat data z jednotlivých řádků a porovnávat je oproti předchozímu stavu (konkrétně td class = "boss_alive" / "boss_dead"). Pokud nastane změna, zanést ji do DB, ale to tak, aby byla dostupná nějaká historie. Tedy, že v tu a tu hodinu a minutu byl změněn stav na tom a tom řádku na tuto a tuto hodnotu.
EDIT: Jde mi především o řešení porovnávání a ukládání dat, parse pomocí XPath zvládnu.
25. 10. 2011 00:10:39
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690640
hm
verified
rating uzivatele
(20 hodnocení)
25. 10. 2011 00:17:18
ok uz chapu, rozhodne budes muset porovnavat vse :) zadna magie co bude hadat co konkretne porovnat nebo neporovnat neexistuje :) neboj, dokud tam nebude tech radku statisice k porovnani v jeden okamzik, tak mas docela fuk kolik jich tam je :) zas tak pomale to nebude ;) a co se db tyka, tak tam budes posilat pouze pozadavek na porovnani na konkretnim rakdu, pri spravne indexaci tak muzes mit treba milion zaznamu a porad to pojede rychle :)
25. 10. 2011 00:17:18
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690639
To, co navrhuješ, bude podle mě fungovat dobře. Status bych přejmenoval na alive a timestamp třeba na change_time (nebo něco jiného, co není rezervované slovo).
Poslední zaznamenaný stav získáš takto
Scrapnutá data projedeš takto
// Transform boss_dead / boss_alive into integers 0 / 1, e.g.
$currentBossStates = array(
'Live Boss' => 1,
'Dead Boss' => 0,
);
$bossChanges = getLastStatesFromDB();
foreach ( $bossChanges AS $lastBossChange ) {
$bossName = $lastBossChange;
if( isset($currentBossStates ) {
if( $currentBossStates != $lastBossChange ) {
// The state has changed, build an update query
}
unset($currentBossStates);
}
}
if( ! empty($currentBossStates) ) {
// Insert new bosses and their current state
}
Kód se doufám vysvětluje sám.
25. 10. 2011 00:32:10
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690638
Bacon
verified
rating uzivatele
(2 hodnocení)
25. 10. 2011 00:34:02
Wow, Martine, já děkuji a smekám.
EDIT: Ach jo, tak ten PHP kód chápu, ale v tom query, co je nad tím, dost tápu.
Mohl bys mi, prosím, Martine, ještě ukázat, jakou strukturu ty databáze mají? Tuším, že toto query obsahuje dvě (boss_states, ve které bude boss_id, boss_name, state_alive a bosses, ve které nevím, co bude...).
Jednoduché operace s DB zvládám, ale JOIN je vyšší liga (navíc mě matou ty ".", myslel jsem, že to slouží k adresování database.table, nebo table.column, ale potom mi nejde do hlavy, jak můžeš používat "state.alive" ještě před samotným boss_states AS state a také boss.id před JOIN bosses AS boss.
Omlouvám se za nechápavost :/
25. 10. 2011 00:34:02
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690637
bendy
verified
rating uzivatele
(5 hodnocení)
25. 10. 2011 09:14:19
vyuzijes-li memcache, tak nemusis pokazde docitat poslednich 200 hodnot z db, ale odbavit to z ni, porovnat zmenu a pripadne identifikovanou ulozit do db, zaorven tedy jeste obcerstvit zaznamy v memcache
25. 10. 2011 09:14:19
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690636
Napsal Bacon;715893
Mohl bys mi, prosím, Martine, ještě ukázat, jakou strukturu ty databáze mají? Tuším, že toto query obsahuje dvě (boss_states, ve které bude boss_id, boss_name, state_alive a bosses, ve které nevím, co bude...).
Je tam to, co jsi říkal v prvním příspěvku. :)
Napsal Bacon;715893
Jednoduché operace s DB zvládám, ale JOIN je vyšší liga (navíc mě matou ty ".", myslel jsem, že to slouží k adresování database.table, nebo table.column, ale potom mi nejde do hlavy, jak můžeš používat "state.alive" ještě před samotným boss_states AS state a také boss.id před JOIN bosses AS boss.
To nevadí, že se ty sloupce používají před určením tabulek. SQL nejprve analyzuje celý dotaz, takže zná aliasy (state, boss) v celém dotazu.
25. 10. 2011 09:42:21
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690635
Bacon
verified
rating uzivatele
(2 hodnocení)
25. 10. 2011 14:58:33
Napsal Martin Schlemmer;715942
Je tam to, co jsi říkal v prvním příspěvku. :)
To nevadí, že se ty sloupce používají před určením tabulek. SQL nejprve analyzuje celý dotaz, takže zná aliasy (state, boss) v celém dotazu.
Děkuji, napadlo mě, že je to tak, jak píšeš a SQL dotaz se provádí až po analýze. Brzo se na to vrhnu, s takto detailním popisem to bude hračka :)
25. 10. 2011 14:58:33
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690634
Tomáš Burda
verified
rating uzivatele
(1 hodnocení)
26. 10. 2011 15:16:00
Nejefektivnější by možná bylo udělat si proceduru přímo v DB a vyhnout se tím přenášení dat z DB do php.
26. 10. 2011 15:16:00
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690633
Bacon
verified
rating uzivatele
(2 hodnocení)
28. 10. 2011 13:00:25
No, nakonec se to nedá nazvat efektivním skriptem ani náhodou, nicméně mám to a funguje to... Hrozný bastl:
Ze strategických důvodů jsem se rozhodl nezveřejňovat kód.
---------- Příspěvek doplněn 30.10.2011 v 09:47 ----------
Teď svůj skript rozšiřuji a měl bych další dotaz... snažím se získat všechna data změn a samotné změny u bosse s určitým ID, to je věc jednoduchá. Nicméně bych rád přímo v MySQL ještě vypočítal, kolik času uplynulo mezi změnou na řádku n a změnou na řádku n-1.
Zkoušel jsem vyplodit nějaký JOIN, který něco dělá, ale dělá to divně...
$query_dbRaidBossTimeline = dibi::query( 'SELECT boss.id, boss.name, boss.level, status.is_alive, status.change_time, TIMESTAMPDIFF(SECOND, status.change_time, status2.change_time) AS time_since_change FROM og_raidboss_status AS status
LEFT JOIN og_raidboss_list AS boss ON (boss.id = status.boss_id)
LEFT JOIN og_raidboss_status AS status2 ON (status2.boss_id = status.boss_id)
WHERE status2.id > status.id AND status.boss_id = %i', $_GET,
'ORDER BY status.change_time DESC' );
Výsledek je skoro správně, jen se některé položky zobrazují 1 - 3x (jeden řádek se zobrazí 3x) a na každém řádku se hodnota time_since_change liší (takže to asi počítá pro každý řádek změny na všech ostatních řádcích)...
Prosím o nějakou radu, ten SQL příkaz jsem střelil jen tak od boku a vůbec se divím, že to něco dělá.
28. 10. 2011 13:00:25
https://webtrh.cz/diskuse/sledovani-zmen-efektivni-ukladani-do-db/#reply690632
Pro odpověď se přihlašte.
Přihlásit