Autor Zpráva
slovakCZ
Profil
Ahoj,

chci se zeptat, jak řešit import dat pro eshop, který trvá přes 45min a na hostingu mi nepovolí nastavit "max_execution_time" na více než 60 sekund. Import samotných už jen dat z XML (přes 7000 záznamů) trvá cca 5 minu a stahování obrázků další desítky minut.

Děkuji za tipy.
Marek88
Profil
Měl bych dva návrhy, ale ani jeden není uplně ideální...

1) Jednodušší je udělat si stejný eshop u sebe na localhostu. Tam to naimportovat (u sebe máš času kolik chceš). Potom exportovat databázi a importovat jí do eshopu na hostingu (třeba po menších kusech) a fotky nahrát přes ftp.

2) Složitější (ale při opakovaném použití rychlejší) možnost je si udělat skript na rozdělení XML souboru na mnoho malých a ty pak nějak ručně nebo automaticky (například pomocí JS a AJAXu) nahrávat do eshopu. Zde může dát trochu práce vytvořit si skript na automatické nahrávání více XML.
Kacko
Profil
slovakCZ:
Nejjednodušší v tomto případě bude se s poskytovatelem domluvit(připlatit), případně pohrozit změnou hostingu.
slovakCZ
Profil
Díky za tipy.

Napadla mě ještě jedna věc a to použití nějakého jednoduchého limitu a offsetu. Při prvním načtení stránky importu definuju limit třeba 50 produktů a offset 0. Prvních 50 tedy naimportuji a poté přesměruju stránku na tu samou, ale s parametrem offset 50, takže přeskočím těch 50, které jsou již naimportované.. atd atd, to je asi jasné. Do těch 60ti sekund se 50 produktů naimportuje, případně dám číslo menší.

Otázka spíše je, jak se zachová "cron". Akceptuje přesměrování? Nebo stránky, které na které bude přesměrováno již "nezpracuje"?
Marek88
Profil
[#4] slovakCZ:
Otázka spíše je, jak se zachová "cron". Akceptuje přesměrování? Nebo stránky, které na které bude přesměrováno již "nezpracuje"?
To sice nevím, ale pokud to nepůjde, tak můžeš použít nějaké přesměrování na straně prohlížeče. Jen je u toho nutné mít v průběhu importu zapnutý prohlížeč.
slovakCZ
Profil
Tak např header('Location: .....'); cron nezkousne... musí se to řešit jinak, ale tím pádem se také nevejdu do limitu 60ti sekund.

Pokud to řeším na straně prohlížeče (při importu je zapnutý prohlížeč), tak prohlížec spadne při nějakém pátém přesměrování, jelikož to vyhodnotí jako zacyklení skriptu (i když se mění parametr). Takže ani tato myšlenka nebyla dobrá.
joe
Profil
slovakCZ:
Zkus přesměrovávat až na načtené stránce. Takže HTML nebo JS po nějakém krátkém intervalu (třeba 5s)
slovakCZ
Profil
joe:
To by možná šlo ale CRON mi toto nezkousne, ten JS úplně ignoruje.

vyřešili jsme to tak, že klient změnil hosting. Má více možností a import probéhl v pořádku.. ale i tak by mě zajímalo, jak to řešit.
Marek88
Profil
Já jsem nedávno potřeboval zmenšit všechny fotky v jednom eshopu. Použil jsem toto:
EDIT:
slovakCZ:
To by možná šlo ale CRON mi toto nezkousne, ten JS úplně ignoruje.
Samozřejmě to nesmíš pouštět CRONem, ale normálně zadat tu adresu do prohlížeče...
V tom mém případě jsem zadal www.mojedomena.cz/?page=velikost a už to běželo.
<?php
// ...
$zacatek = microtime(true);
if (!isset($_GET["od"]) || !isset($_GET["limit"])) {
    echo "<script>
    window.location='?page=velikost&od=0&limit=100'; // zde se dá nastavit jiné číslo než 100 pro jiný počet záznamů
</script>";
    exit;
}
$od = $_GET["od"];
$limit = $_GET["limit"];

// vybrání adres fotek z DB a jejich zmenšení

$konec = microtime(true);
echo "Celkový čas: " . ($konec - $zacatek) . " s.";

$od = $od + $limit;
if ($od < 10000) { // omezení aby to neběželo do nekonečna (i bez toho se mi to nikdy "nezacyklilo" a pořád se to načítalo dál a dál)
    echo "<script>
    window.location='?page=velikost&od=$od&limit=$limit';
</script>";
}
// ...
?>
joe
Profil
slovakCZ:
Proč přes CRON? Myslel jsem přes prohlížeč, vlastně už to napsal Marek88
slovakCZ
Profil
no, cron proto, ze si moc neumim predstavit, ze bych kazdy den nekdo otevrel prohlizec, zadal url a cekal hodinu nez se import provede..
Marek88
Profil
[#1]slovakCZ:
Import samotných už jen dat z XML (přes 7000 záznamů) trvá cca 5 minu a stahování obrázků další desítky minut.
[#11]slovakCZ:
no, cron proto, ze si moc neumim predstavit, ze bych kazdy den nekdo otevrel prohlizec, zadal url a cekal hodinu nez se import provede..“.

Netušil jsem, že tam budete každý den nahrávat 7000 nových produktů i s obrázky.

V tom případě je už vhodné dohodnout se s hostingem na dlouhém limitu (pokud je hosting ochotný) nebo si pořídit vlastní server.

Pokud to ale nejde, tak výše zmíněný způsob je pořád možný a nikdo nemusí čekat u otevřeného prohlížeče hodinu. Stačí to nechat otevřené v jiném panelu a mezitím vyřizovat objednávky nebo to upravit tak, aby to fungovalo v iframu "jakoby na pozadí" při vyřizování objednávek.
slovakCZ
Profil
Špatně jsem to asi popsal. Samozřejmě, že ne vždy se bude importovat 7000 obrázků, ale ověřuje se, zda existuje hlavní obrázek a zda existují všechny jeho miniatury.. už jen to (i když se obrázek nestahuje) zabere pár minut a do jedné minuty se určitě nevejdu.

No my to vyřešili jiným hostingem, spíše mě zajímá, jak tuto situaci řešit. Například eshop superqc.com to řešené má, ale v té třídě pro import se zatím nemůžu pořádně zorientovat. Musím si na to najít více času.

Jinak aby to bylo v iframu např při vyřizování objednávek v tomto případě možné není, jelikož eshop je bezúdržbový a zcela zautomatizovaný (objednávky se přeposílají jinam). Nehledě na to, že problém nastává, pokud otevřu import v jedné záložce tak v jiné záložce nejsem schopen s webem pracovat. Nevím zda je to standartní chování nebo mám jen nějak špatně nastavené všechny prohlížeče, ale pokud mi import běží v jednom prohlížeči tak se mi nenačte z té domény žádná jiná stránka i když je v záložce jiné. To musím řešit tak, že import spustím např v IE a v Chromu po webu brouzdám již normálně... zajímavé :o)
slovakCZ
Profil
nenapada nekoho jeste nejake reseni?
ahoj
Profil *
Jaké řešení ještě hledáš? Jde je o to, jak tu zátěž nejlíp rozložit v čase. Spočítej si, kolik těch akcí za 24 hodin musíš stihnout, vyrob si úlohu nebo úlohy pro cron a nastav jim časy, kdy máš na webu nejmenší provoz.
slovakCZ
Profil
O to nejde, ja import muzu pustit klidne na obed a na rychlost webu to nema vliv. Problem je v tom, ze cely import trva 45 minut, ale na hostingu je povolena doba vykonani skriptu jen 1,5 minut. Import skonci tim padem na chybe.

Napadlo me jeste reseni, ze si budu pocitat, jak dlouho uz import bezi. Pokud import pobezi uz 1 min a 20 sekund napriklad, tak ho ukoncim a do databaze si ulozim, u jake polozky jsem skoncil. Kdyz se import spusti znovu, zjisti se nedjriv, zda v databazi je ulozena nejaka posledni polozka a pokud ano, tak se zacne import provadet od ni. Cron by se ale musel nastavit an daleko mensi intervaly. Myslite, ze je to dobre reseni? Nic jineho me uz nenapada.
ahoj
Profil *
slovakCZ:
na hostingu je povolena doba vykonani skriptu jen 1,5 minut.

Ten čas lze nastavit, je to věcí dohody a možná nějakého drobného poplatku.

Napadlo me jeste reseni, ze si budu pocitat, jak dlouho uz import bezi. Pokud import pobezi uz 1 min a 20 sekund napriklad, tak ho ukoncim a do databaze si ulozim, u jake polozky jsem skoncil. Kdyz se import spusti znovu, zjisti se nedjriv, zda v databazi je ulozena nejaka posledni polozka a pokud ano, tak se zacne import provadet od ni. Cron by se ale musel nastavit an daleko mensi intervaly. Myslite, ze je to dobre reseni? Nic jineho me uz nenapada.

To je v podstatě to, co jsem psal já, jen s tím rozdílem, že ty chceš měřit čas a já jsem navrhoval nastavit to nějak empiricky.
Mike8748
Profil
slovakCZ:
z XML (přes 7000 záznamů) trvá cca 5 minu
taky je otazka jakým způsobem se to XML zpracovává... 5 minut na 7000 položek je možna i docela dost. (možná ve skriptu nahradit DOM třeba SimpleXML, může to pomoct)

a stahování obrázků další desítky minut.
ty obrázky nemusíš stahovat okamžitě. do databáze si akorát uložíš že nějaký takový obrázek existuje, a když přijde požadavek na zobrazení toho obrázku, tak se přes skript podíváš do místní složky, zda obrázek existuje, pokud ne tak se stáhne (stažení jednoho obrázku je na pár vteřin) a až pak zobrazí.
slovakCZ
Profil
ahoj:
Cas bohuzel nastavit nelze, ani za pravidelny mesicni priplatek, uz jsem to s nimi resil a klient si nemuze dovolit prejit k jinemu hositngu. Nejsou nam schopni dat navyseni ani na pamet ani na cas pro urcity skript.

No, asi jsem to spatne pochopil ale nezda se mi to to same, co si psal ty... kdyz vezmu vpotaz, ze import vsech 5000 polozek sezere pres 200MB pameti, tak by nepomohlo spoustet skript ani v noci. Pamet na servru je max. 125mb.. tam by pomohlo leda to, import prepsat tak aby se nejdrive importovaly produkty, v jinem skriptu jen obrazky atd atd.. ale prave to stahovani obrazku zere nejvice. Mozna jsem te jen spatn pochopil a vylozil si tvoji vetu trosku jinak.

Mike8748:
SimpleXML samozrejme vyuzivam. Ale nejvice casu zabere samotne stahovani obrazku. V XML je ulozena informace, na jake URL se obrazek nachazi a ja uz ve skriptu importu tyto obrazky z URL stahuju, zmensuju a pracuju s nimi. TO je nejvetsi zrout a zpomalovac. Samozrejme by to slo vyresit i tak, ze bych si URL obrazku jen poukladal do db a v jimen skriptu bych prochazel tuto databazi a obrazky postupne zpracovaval.

:o) tak koukam, ze v dalsim odstavci si psal neco podobneho co ja v textu o par radku vyse :o) kdybych si prescetl nejdrive cely tvuj prispevek tak bych si toho vsiml.


Ja ani tak nedumam nad tim, jak cas importu zkratit. Jestli obrazky stahovat hned nebo ne... ja uz ten import vyresil trosku jinak, ale porad me v hlave lezi ta otazka, jak podobne veci resit, kdyby tady jine varianty nebyly. TO, ze obrazky muzu zpracovavat pozdeji je hezke, ale co kdyz nekdy nastane situace (nemluvim zrovna o tomto importu, ale vice obecne), kdy se opravdu budu muset spolehnout na to, ze skript musi vykonat nejake vypocty a tyto vypocty se nevejdou napriklad do pameti. Co pak?

Chvili jsem si s tim hral a ten muj posledni napad neni vubec spatny. Vyresil jsem to tak, ze pokud se blizi memory limit nebo max_execution_time ke sve hranici, tak import ukoncime a ulozime si informaci o tom, kde jsme skoncili.. pri dalsim spusteni importu budeme pokracovat tam, kde jsme skoncili.. budu rad za nejake napady jestli by to slo napsat treba i jednoduseji:
<?php
// kouknu se do databaze, zda existuje nejaky offset. Pokud neexistuje znamena to
    // ze import je spusten poprve a nebo predchozi import dobehl cely az do konce
    // V takovem pripade nastavime offset = 0
    $offset = 0;
    
    // zjistime si pomoci ini_get('memory_limit') jaka je hodnota memory_limitu
    // helikoz tato fce vraci napr 128M tak orizneme M a udelame z toho int:
    $memory_limit = 128;
    
    // to same pro max_execution_time, takze napr takto:
    $time_limit = (int) ini_get('max_execution_time');
    
    // cas, kdy byl import spusten
    $start_time = time();
    
    // nastavime si iterator ($i) na nulu
    $iterator = 0;
    
    // iterujeme pres polozky XML
    foreach($xmldata as $item) {
        
        // Pokud je iterator+1 mensi nebo roven offsetu, tak tyto polozky preskocime
        // jelikoz se naimportovaly v minulem spustenem importu.
        if(($iterator+1) <= $offset && $offset != 0){
            $iterator++;
            continue;
        }
        
        // zjistime si cas, ktery nam zbyva do vyprseni max_execution_time
        $time_left = $time_limit - (time() - $start_time);
        
        // zjistime si, kolik nam zbyva jeste pameti
        $memory_left = $memory_limit - round(memory_get_usage(true) / 1024 / 1024, 1);
        
        // pokud se zbytek pameti nebo cas blizi ke kritickym hodnotam, ktere
        // jsem zvolil 1.5MB pro pamet a
        // 5 sekund pro max_execution_time tak import ukoncime a do databaze
        // ulozime informaci o tom, u jake polozky jsme skoncili
        if($memory_left<1.5 || ($time_limit && $time_left <= 5)) {
            if($offset>0){
                // pokud offset != 0 tak upravime v databazi radek, kde mame
                // tento offset ulozen. Takze neco takoveho:
                $db->update->tabulka->(array('offset' => $iterator));
            }else{
                // pokud je offset == 0, tak se jedna o prvni import. V tom pripade do databaze
                // tuto informaci ULOZIME
                // takze neco takoveho:
                $db->insert->tabulka->(array('offset' => $iterator));
            }
        }
        $iterator++;
        
        // no a tady zpracujeme polozku XML. stahneme obrazek, ulozime ji do 
        // databaze, nebo ji v databazi aktualizujeme pokud jeste neexistuje...
    }?>

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: