Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Lepší návrh PHP/SQL pro získání dat a následný zápis?

Zdravím,
momentálně pracuji na projektu mujstream.cz - jedná se o databázi Českých a Slovenských online streamů.
Web je ve výstavbě a většina funkcí není aktivní, už teď ale narážím na problém, který musím nějak řešit.
V podstatě jde o to, že abych zjistil, zda je nějaký stream online a jaký počet diváků má, musím to pravidelně kontrolovat a následně zapisovat do databáze (zde každých 15 minut pomocí funkce CRON).

Bohužel jsem samouk a neznám jiný způsob než ten, který jsem sepsal.
Script je funkční, ale je příliš pomalý a za výsledek to má, že v pravidelných intervalech, kdy script právě probíhá se stránka nepřiměřeně dlouho načítá (lagne se, dokud se script nedokončí). Při cca 66 záznamech v databázi trvá tomuto scriptu provedení asi 3 minuty!

Nevím jak to lépe řešit, napadlo mě snad jen hodit script na jinou stránku (kterou nevyužívám) a tím vlastně eliminovat lagnutí této databáze (šlo by to?)

Script jako takový je zde

<?php
  require('/dibi.php');
  require('/cnf.php');
  $stream = dibi::query('SELECT * FROM users')->fetchAll();

  foreach($stream as $s){
    $clientId    ='*';
    $channelName = $s['twitch'];
    $json_array  = json_decode(file_get_contents('https://api.twitch.tv/kraken/streams/'.strtolower($channelName).'?client_id='.$clientId), true);

    if ($json_array['stream'] != NULL) {
      $viewers = $json_array['stream']['viewers'];

      $cron = array(
        'online'  => '1',
        'viewers' => $viewers
      );
      
      dibi::query('UPDATE users SET', $cron, 'WHERE twitch=%s', $channelName);
    } else {
      $cron = array(
        'online'  => '0',
        'viewers' => '0'
      );

      dibi::query('UPDATE users SET', $cron, 'WHERE twitch=%s', $channelName);
    }
  }
?>

Děkuji za případné rady, popř. ukázky jak to řešit.
Pěkný den přeji!

Předmět Autor Datum
ahoj, vše je v pohodě a chválím za dibi :) .. jinak k tvému problému. čmuchám že problém bude v file…
tomas.kulhanek 17.10.2013 16:58
tomas.kulhanek
nějak tady blbne highlighter... -k samotnému algoritmu nediv se, když sekvenčně děláš 66 požadavků…
mnua.al 17.10.2013 17:35
mnua.al
==> zjisti, zda api umožní hromadný dotaz, ==> nebo dotazy paralelizuj, ale jelikož je php zastaralý… poslední
Eessencia 18.10.2013 06:52
Eessencia

nějak tady blbne highlighter...

-k samotnému algoritmu

nediv se, když sekvenčně děláš 66 požadavků
3min/66≃ 3 sekundy ... pokud je to někde v zámoří, tak to není nic neobvyklého na druhou stranu jsem si teď ověřil, že požadavek trval 1.2 sekundy
==> zjisti, zda api umožní hromadný dotaz,
==> nebo dotazy paralelizuj, ale jelikož je php zastaralý jazyk, buď to jde pomocí fórků nebo curl_multi. Případně pro PHP existuje React.php.

Další průšvih je, že se během skriptu 66x zapisuje do databáze. Proč to neudělat chytře a hodnoty si uložit nejdřív do pole a a pak udělat jeden velký update v databázi. (Paradoxně tohle možná bude pracnější, než současné ledabylé řešení) A ne vždy je to taky lepší řešení a je třeba provnat pro a proti

Dál v ukázce postrádám ošetření chyb...
A o úrovni kódu( používání CDD - CopyPaste Driven Development) už vůbec...
Tohle je přece mnohem hezčí:

    $cron = array(
	'online'  => '0',
	'viewers' => '0'
	);

if($json_array['stream'] != NULL){
	$viewers = $json_array['stream']['viewers'];

	$cron = array(
		'online'  => '1',
		'viewers' => $viewers
		);     
}
dibi::query('UPDATE users SET', $cron, 'WHERE twitch=%s', $channelName);

To by byl asi taková do očí nejvíc bijící nešvar...

Další věc - aplikace není vůbec rozvrstvená...(v v souborů napevno používáš dibi jako úložiště)- to ti nevadí?

A pak samotné podstatě problému: Jak jsem snažil pochopit, ty jsi psal, že by dobré řešení byl CRON, ale ty jsi místo něj udělal to, že při každém požadavku se získávají data?! To se pak nediv. Když už je zvoleno takovéhlýhle otřesný způsob, tak by stálo aspoň ty data načítat jen, pokud jsou starší než 15 minut.
To lze implementovat pohodlně v nette, že si vytvoříš CacheStorage a nad Ním cache a záznam do ní uložíš s flagem EXPIRE. Nebo pokud nette neznáš, změnit kód stránky tak, že tam vložiš podmnínku, zda jsou , že pokud jsou data starší něž načtený timestamp, tak že je načteš z webu a uložíš kamkoli a s tím současně zapíšeš aktuální timestamp.

==> zjisti, zda api umožní hromadný dotaz,
==> nebo dotazy paralelizuj, ale jelikož je php zastaralý jazyk, buď to jde pomocí fórků nebo curl_multi. Případně pro PHP existuje React.php.

Zjistím, zkusím.

Další průšvih je, že se během skriptu 66x zapisuje do databáze. Proč to neudělat chytře a hodnoty si uložit nejdřív do pole a a pak udělat jeden velký update v databázi. (Paradoxně tohle možná bude pracnější, než současné ledabylé řešení) A ne vždy je to taky lepší řešení a je třeba provnat pro a proti

Vyzkouším, osobně jsem myslel, že to na rychlost nebude mít vliv, protože největším zpomalovákem bude ono tahání dat z twitch.tv.

Dál v ukázce postrádám ošetření chyb...

Jak jsem říkal, jsem samouk a dělám to jen ve svém volném čase a pro zábavu, nikoliv pro peníze. Když něco nevím, není to tím, že jsem idiot, ale že jsem se to ještě nenaučil. Jaké chyby byste např. ošetřoval?

A o úrovni kódu( používání CDD - CopyPaste Driven Development) už vůbec...

Tomuto bohužel nerozumím a nevím co si pod pojmem CDD představit.

Tohle je přece mnohem hezčí:

Podle tohoto předpokládám, že se jedná o formátování kódu samotného. V tomto případě si nemyslím, že Vaše "ukázka" je přehlednější a "hezčí" než ta má.
Odsazování pomocí dvou mezer jsem se naučil při studiu RoR (Ruby on Rails) a jsem s tím spokojen. Kód je pro mě velmi přehledný a dostatečně "hezký".

Další věc - aplikace není vůbec rozvrstvená...

Bohužel netuším jak bych ji měl rozvrstvit.

(v v souborů napevno používáš dibi jako úložiště)- to ti nevadí

Tomuto nerozumím, jak jinak bych to měl použít?

Jak jsem snažil pochopit, ty jsi psal, že by dobré řešení byl CRON, ale ty jsi místo něj udělal to, že při každém požadavku se získávají data?! To se pak nediv. Když už je zvoleno takovéhlýhle otřesný způsob, tak by stálo aspoň ty data načítat jen, pokud jsou starší než 15 minut.

Já jsem nepsal, že by byl dobrým řešením CRON, já jsem napsal, že script se spouští automaticky sám, každých 15 minut pomocí CRONu.

takovéhlýhle otřesný způsob

Jak jsem již psal, jsem samouk, nejsem placen za to, abych se učil 24/7 efektivní a správný postup. Lépe jsem to vyřešit nedokázal a proto jsem se zde zeptal.

Jsem rozespalej, tak snad jsem odpověděl na vše. V žádném případě to nemyslím zle, jen jsem si dovolil reagovat postupně.

Zpět do poradny Odpovědět na původní otázku Nahoru