PHP , MySQL adatok mentése fájlba. SOK

PHP , MySQL adatok mentése fájlba. SOK
2021-08-08T13:41:13+02:00
2021-11-09T21:27:20+01:00
2022-10-15T21:21:36+02:00
sediqwe1
Sziasztok!
Sok adatot tárolok (nekem sok) egy adatbázisban, és ezeket szeretném fizikai fájlként lementeni.
Mivel elég amatőr programozó vagyok, elég sokáig tart ez a jelenlegi scripttemmel. 
Valahogy nem hiszem hogy ennek így kellene zajlania :)
Alapból végig megyek a filename táblán, és az ott található filename alapján mentem a dolgokat.
majd lekérem az "eredeti" táblában azokat a sorokat amikben a filename_id azonos éppen azzal az ID vel és azt berakom egy $vég változóba soronként és azt mentem ki mindig.
Ezt én tákoltam, így elnézést a programozóktól akik most kaptak szívrohamot :DDDDD
kb 250.000 "eredeti" sorom és 85.000 "fordítas" sorom van, illetve összesen 610 fájl
A fájlok mentésen nem ritkán megszakad időtúllépéssel, vagyis hát a szerver nem válaszol.. csak vár... 
már szétszedtem a scriptet, 500 kis, és 110 nagyobb fájlt generálok, de ez se az a megoldás ami csodát csinálna.

$result = $connect->lekeres_lower("*", "filename", "","0" , "0" ,"order by sorszam ASC"); while($connect->lekeres_fetch($result , 'assoc')){ list($id,$filename,$status,$sorszam,$kesz) = array_values($connect->row); $megszamolom = $connect->lekeres_row_num("*","eredeti" , "filename_id = 610","","","");// megszámolom hogy mennyi eredeti tartalom van a fájlban! Ha üres akkor nem írom be a fájl kezdő és vég sorát SEM! $vég = "Version 2 30\r\n"; //Eredeti fájl verzió $i=0; //Fájl sorszámlálója //ITT NÉZEM MEG HOGY HA A FÁJL STÁTUSZA 4 akkor mehet a KÉSZ MAPPÁBA if($status == 4){ //Ha státusza négy, akkor a KÉSZ be rakja $myfile = fopen("file/kesz/".$filename.".oxt", "w")or die("Unable to open file!"); } else{ $myfile = fopen("file/".$filename.".oxt", "w")or die("Unable to open file!"); } $result2 = $connect->lekeres_lower("*", "eredeti", " filename_id = 610 $info","0" , "0" ,""); while($connect->lekeres_fetch($result2 , 'assoc')){ list($id_1,$elso_1,$masodik_1) = array_values($connect->row); if($i==0 && $megszamolom!=0) // Ha $i még 0 és a fájl hosszabb mint nulla, akkor berakja a nyitó zárójelet! { $vég = $vég."{\r\n"; } $i++; //Növelem a sorszámát. @$k3 = $connect->lekeres_gyors("*","forditas"," elso LIKE '".$elso_1."' and status = 2","0","0","","assoc"); //Megnézem hogy található e olyan elfogadott (STATUS 2) fordítás ami nekem kell, ha igen, azt teszem be! if(@strlen(@$k3["masodik"])>0) { $elso_1 = str_replace("GLOBALXXXXX_","",$elso_1); $vég = $vég."\t".trim($elso_1)." = " . trim(@$k3["masodik"])."\r\n"; }//Ha nincs olyan fordítás ami elfogadott akkor -> else { @$k4 = $connect->lekeres_gyors("*","forditas"," elso LIKE '".$elso_1."' and status = 0 and fordito_id = 1","0","0","","assoc"); $elso_1 = str_replace("GLOBALXXXXX_","",$elso_1); //Megnézem van e olyan fordítás ami nincs elfogadva de eredeti fordítás. if(@strlen(@$k4["masodik"])>0) { $vég = $vég."\t".trim($elso_1)." = " . trim(@$k4["masodik"])."\r\n"; } else{//Ha nincs ilyen, beteszem az angol szöveget. $vég = $vég."\t".trim($elso_1)." = " . trim($masodik_1)."\r\n"; } } }//While end if($megszamolom!=0) { //Beteszem a vége lezáró karaktereket, ha a fájlnak van tartalma $vég = $vég."}\r\n"; //Fájl vége lezáró karakterek. } fwrite($myfile, pack("CCC",0xef,0xbb,0xbf)); //Fájl kiirás UTF-8 BOM mal!!!! fwrite($myfile, $vég);//Fájlba írás fclose($myfile); // Fájl lezárás $szam++; } }
Mutasd a teljes hozzászólást!
Alaposan nem néztem át, de egy dolgot felejts el: ciklusba SQL lekérdezés. Ilyet nem csinálunk. Egy nagy lekérdezés legyen (vagy csak a lehető legkevesebb számú), és azt dolgozd fel. Ha több táblából kell összeszedni az adatokat, arra való a JOIN. Ha ezzel megvagy akkor a következő lépés az, hogy a hosszú futási időt igénylő szkripteket nem a webszerveren át futtatjuk, hanem CLI-ből.
Mutasd a teljes hozzászólást!

  • Nincs véletlenül a MySql-nek saját eszköze a mentésre, amit mindenféle PHP nélkül lehetne használni?
    Mutasd a teljes hozzászólást!
  • Az a "baj" hogy nekem egy speciális sort kell az adatokból letrehozni. 
    Mert
    id = szöveg
    lesz a végen
    Ezert a nyers mysql mentés nem jó.
    Mutasd a teljes hozzászólást!
  • És ha lenne egy külön program, ami a fájlod végére oda tudja tenni, hogy `id=szoveg` ?
    Mutasd a teljes hozzászólást!
  • - mennyi idő a "sokáig"?
    - hány rekord van az egyes táblákban? (filename, eredeti, forditas)
    - meg vannak indexelve a táblák? 
    - miért 610-re szűrsz a $megszamolom lekérdezésnél?
    - honnan jön az $info?
    - mit jelent az $elso_1 és $masodik_1?
    Mutasd a teljes hozzászólást!
  • Ezt igy nem igazan ertem , van egy adattablam, amit ki kell mentenem ilyen formatumban:
    id = szoveg.
    ID is es a szoveg is a tabla egy egy cellajabol jon , ertelem szeruen...bar lehet hogy a leirasom nem volt a legegyertelmubb... :) Bocsi.
    Mutasd a teljes hozzászólást!
  • - mennyi idő a "sokáig"?
    - hány rekord van az egyes táblákban? (filename, eredeti, forditas)
    - meg vannak indexelve a táblák? 
    - miért 610-re szűrsz a $megszamolom lekérdezésnél?
    - honnan jön az $info?
    - mit jelent az $elso_1 és $masodik_1?


    -1.: Tul sok, annyi hogy nem fut le a script, de jelenleg a php nak adtam 6 percnyi idot, az nem eleg. 
    ugy fut le hogy 2 fele bontottam, meret szerint, ez 1-500 es 501-609 ig tart... miutan meret szerint rendeztem az elkeszitendo fajlokat.
    -2:
     Eredeti ben ca 250.000 (nem mindegyik sort kell forditani a kesobbiekben, de minden sort le kell irni a fajlba, vagy az eredetit (ha a status =2 akkor pedig a hozza tartozo forditast)
      Filename: 609
      Forditasban folyamatosan bovulve, korulbelul jelenleg 45.000 (itt 1 eredetihez akar tobb forditas lehet, de csak a status = 2 vel megjelolt az amit be kell irnom a fajlba, ha nincs ilyen, akkor az eredeti marad.

    3. Igen, az elsore es a masodikra igen, mind a ketto.
    4. a 609 tenyleges fajlunk van, a 610 egy anomalia fajl, ami felulirja a 609 et, ha.... erre van kulon mentesem hogy mi szerint. tehat a 610 nem kell, nem letezo fajl.

    5. $info egy altalam megadott adat, nem lenyeges jelenleg (fejbol nem is tom mit takar , lichtensteinben vagyok epp, nem latok ra erre a gany kodomra hogy mire is gondolhattam anno :DD)

    6 $elso_1 $masodik_1 altalaban akkor van ha nagyon szerencsesen egy belso ciklust futtatok egy cikluson belul, es nem szeretnem hogy veletlen felulirjam a kulso ciklus hasonloan elnevezetett valtozoit... 


    Mint latszik, vagy ha nem is, teljesen magamtol hegesztettem a scriptjeim, nem tanultam, nem fogta senki a kezem... ennek megfeleloen olyan is amilyen.
    Mutasd a teljes hozzászólást!
  • Szokás szerint beleszólok,  bár nem értek hozzá...

    Ez egy rendszeresen futó program lenne?
    Feltétlenül muszáj php-ből?
    Amennyire értem az elvárásaidat, azok simán sql-ből is megoldhatóak (lásd: nem értek hozzá -> neked kellene a doksiból előtúrni a mikéntjét, de az biztos,  hogy megy)
    A mysql select tudtommal rendelkezik egy INTO OUTFILE opcióval, bár ez mintha csak szerver oldalra tudna pakolni (lásd doksi, mivel ebben sem vagyok biztos - főleg, hog, biztonsági szempontból annyira nem jó ötlet ha a kliens a szerver fájlrendszerét tudja használni)
    Mutasd a teljes hozzászólást!
  • Mivel a problema fent all tovabbra is, (valamiert a valaszokrol nem kaptam ertesitest, elnezest hogy ilyen kesve reagalok) ezert probalkoztam en is egysmassal.
    Kikerultem a gondot: 
    - 100 fajlonkent legeneralom a 609 fajlt... nem elegans, sok kattintas, nem jo, de megy.
    Gondolkodtam hogy mi lenne ha tombositve tarolnam a 2 tabla tartalmat?
    tehat lenne egy eredeti_array , es egy forditas_array, amikben benne van minden...
    mondanom se kell hogy sikerult az osszes memoriat felzabalnom, itt alltam meg jelenleg ... pedig otletnek jo volt :DDDD
    Mutasd a teljes hozzászólást!
  • de nekem a kimenet nem mind1 hogy nez ki. 
    Most a tenyleges file kimenet pl ilyennek kellene legyen

    Version 2 30 { ABGAIL2_HINT = ~INPUT_VEH_CIN_CAM~ megnyomásával ráfókuszálhatsz Abigailre. ABGAIL2_WANTED = Rázd le a zsarukat! }
    ezt egy "abgail2.oxt" fileba mentem pl.
    mivel a user nem ert a filok manipulalasahoz, igy ez tunt a leg kezenfekvobbnek, PHP - Mysql bol lekerni az adatokat, ID = SZOVEG minta alapjan kiiratni , elore es a vegere a jeleket bevesni... es elmenteni...
    Mutasd a teljes hozzászólást!
  • Hát soronként még tudom, hogy bármilyen formátumot létrehozhatsz, de ez, ha nem akarsz json-t helyette... akkor passzolom.
    Mutasd a teljes hozzászólást!
  • nem kellene, hogy ennyire lassú legyen. A mai gépeknek 200000 sor nem okoz problémát, hacsak nem extrém hosszú sorok.

    A $megszamolom lekérdezésben a szűrőfeltételed mindig fixen 610. Nem pl. $id-re kellene szűrnöd? Így ugyanazt kérdezed le 609-szer. $result2-nél ugyanígy.

    Az eredeti táblában a filename_id mező alapján szűrsz, tehát az nagyon fontos, hogy azon legyen index.

    A forditas táblában Like-kal szűrsz, ami szöveges összehasonlítást jelent minden egyes lekérdezésben minden sorra külön. Szerencsésebb volna valami azonosító (egész szám) mezőt gyártani, azzal jóval hatékonyabban dolgoznak az adatbáziskezelők.

    a microtime() függvény egy időbélyeget ad vissza php-ben. Ha a ciklusaidon belül ennek értékét valami magyarázó szöveggel kiírod egy fájlba, képet kaphatsz arról, melyik programrész mennyi ideig fut.

    Pl. a külső ciklusban:

    file_put_contents("log.txt", "$id $filename ".microtime(true)." \n", FILE_APPEND );
    Mutasd a teljes hozzászólást!
  • Végül az lett amit írtál, 
    Fogtam végig mentem 1x a fájlokon.
    Minden fájl elején fogtam bepakoltam minden nekem kellő dolgot egy tömbbe.
    Ez lett az 'eredeti_list[][]'
    Majd fogtam és a fordításnál is megcsináltam ugyanezt. természetesen az adott fájlra szürve csak a szűrt listát kértem már le.

    És az eredeti listán, ami minden sort tartalmazott, végig menve, a hozzá tartozó fordítás_list ből kiszedtem a találatot , ha nem volt akkor pedig az eredeti lista eredeti szövegét használtam :)
    Így a 2xkitudja mennyi időből sikerült 
    1x2 percet csinálnom úgy hogy ebben már benne van a fájlok kiirása, becsomagolás, törlése, etc. LÉNYEGESEN lassabb, 1x se futott még lyukra. 
    Illetve ha csak az eredeti lista kell akkor félperc alatt elkészül, hiszen akkor nem kell összehasonlítgatnia , keresnie. Köszönöm a segítséget! Lehet hogy menne másnak ez messze gyorsabban is, de nekem éppen megfelelő :) Köszi még1x!!!!!
    Mutasd a teljes hozzászólást!
  • A Te hozzászólásodból kivettem az időméréses ötletet, így már tudom hogy mennyi az annyi :) 2.2 perc alatt szokta összedobni a dolgokat, 3 felé még soha nem ment, nyilván egy bérelt indonéziában lévő gép minimál csomaggal... öröm így is van! 
    Filename_id -n van index , "természetesen" (nálan nem az :D haver mondta annó hogy ugye van... persze, ugye volt :DDD (nyilván nem :\ )
    Mutasd a teljes hozzászólást!
  • pardon, lényegesen GYORSABB :)
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd