Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP][AJAX] Import danych z dużego pliku XML
duch4ever
post
Post #1





Grupa: Zarejestrowani
Postów: 155
Pomógł: 0
Dołączył: 22.06.2010

Ostrzeżenie: (0%)
-----


Witam, mam spory plik z hurtowni (prawie 40MB) i chcę go zaimportować przez PHP do bazy danych. Napisałem sobie skrypt który przez ajax stopniowo dodaje/aktulizuje dane ($xml->read()) jednak nie jest to dość optymalne i działa kilka godzin (skrypt otwiera plik, zczytuje część danych i zamyka). Można to zrobić jakoś lepiej? Może jest jakiś sposób o którym nie wiem?

Pliku oczywiśćie nie moge zczytać w całości gdyż skrypt musi działać na wirtualnym serwerze przy 128MB pamięci dla PHP. Bardzo proszę o pomoc.
Pozdrawiam

Ten post edytował duch4ever 26.11.2012, 15:10:37
Go to the top of the page
+Quote Post
zegarek84
post
Post #2





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

Ostrzeżenie: (0%)
-----


Cytat(duch4ever @ 26.11.2012, 15:09:46 ) *
Witam, mam spory plik z hurtowni (prawie 40MB) i chcę go zaimportować przez PHP do bazy danych. Napisałem sobie skrypt który przez ajax stopniowo dodaje/aktulizuje dane ($xml->read()) jednak nie jest to dość optymalne i działa kilka godzin (skrypt otwiera plik, zczytuje część danych i zamyka).

nie opisałeś jak to robisz, samo xml->read() nic nie mówi ;p
Cytat(duch4ever @ 26.11.2012, 15:09:46 ) *
Można to zrobić jakoś lepiej? Może jest jakiś sposób o którym nie wiem?

Pliku oczywiśćie nie moge zczytać w całości gdyż skrypt musi działać na wirtualnym serwerze przy 128MB pamięci dla PHP.

Jasne, że można i można to zrobić przy mniej dostępnej pamięci ;p

do google hasło "SAX PHP" - będziesz miał też odwołanie do manual'a PHP "XML Parser", jednak poczytaj sobie toutoriale jak z tego korzystać... całość będziesz musiał napisać zdarzeniowo w PHP podpinając callbacka pod parsera, oczywiście Tobie będzie potrzebna bardziej skomplikowana obsługa dynamicznych zdarzeń niż w przykładach, które znajdziesz w google...

w tym parserze będziesz miał info, do jakiego tagu wchodzisz, poziom zagłębienia itd... w PHP zdarzeniowo funkcje czy metody klas możesz wywoływać np. w ten sposób $this->{'moja_metoda'}($argument) oraz poczytaj o callbackach w PHP http://www.php.net/manual/en/language.types.callable.php

dodatkowo możesz w bazie przechowywać jakiś unikalny zewnętrzny harakterystyczny klucz... dodając do bazy nie dodaj do tej tabeli tylko do tymczasowej o tej samej strukturze w transakcji rekord po rekordzie (i nie zapamiętuj tych miennych), po dodaniu wszystkich rekordów do tabeli tymczasowej wykonaj zapytanie (inserta) dodające rekordy z tabeli tymczasowej do tabeli docelowej po kluczach unikalnych zewnętrznych (harakterystycznych) których nie ma w tabeli docelowej (chyba to się nazywa iloraz na danych bazy - ale to tylko ciekawostka nazewnictwa ;p), czyli INSERT SELECT hasło...

o dodawaniu wartości do tabeli tymczasowej wspomniałem dlatego, iż ja nie byłem pewnych danych które będą dopisywane do bazy czy czasem się nie powtórzą - pewne statystyki robiłem na bazie zewnętrznych danych XML jakieś 1,5 roku temu... a ponieważ dane nie są sprawdzane po stronie klienta czy istnieją w bazie a dopiero przez samą bazę to to działa dosyć szybko...
Go to the top of the page
+Quote Post
duch4ever
post
Post #3





Grupa: Zarejestrowani
Postów: 155
Pomógł: 0
Dołączył: 22.06.2010

Ostrzeżenie: (0%)
-----


Dzięki kolego, troszkę poczytałem i testuję. Mój dotychczasowy skrypt działa mniejwięcej tak:

  1. $xml = new XMLReader();
  2. if(!$xml->open('XML.xml'))
  3. return false;
  4.  
  5. while($xml->read())
  6. {
  7. if($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'produkt')
  8. {
  9. // kod
  10. }
  11. }


Możesz wyjaśnić czym metoda podana przez ciebie różnie się od tej? Z tego co wstępnie zauwazyłem moja metoda nie pobiera pamięci bo nie ładuje pliku do ramu natomiast podana przez ciebie na start zabiera 40MB. Sprawdzałem wypisanie pozycji z XMLa (niecałe 20 000 pozycji, zwykłe echo). Szybkościowo działają dość podobnie, może o czymś nie wiem więc pytam.

Wydaje mi się że dzięki temu mam lepsze poruszanie po pliku XML tak?
Dizęki wielkie za zainteresowanie.
Go to the top of the page
+Quote Post
zegarek84
post
Post #4





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

Ostrzeżenie: (0%)
-----


Cytat(duch4ever @ 26.11.2012, 17:46:15 ) *
Możesz wyjaśnić czym metoda podana przez ciebie różnie się od tej? Z tego co wstępnie zauwazyłem moja metoda nie pobiera pamięci bo nie ładuje pliku do ramu natomiast podana przez ciebie na start zabiera 40MB. Sprawdzałem wypisanie pozycji z XMLa (niecałe 20 000 pozycji, zwykłe echo). Szybkościowo działają dość podobnie, może o czymś nie wiem więc pytam.

Wydaje mi się że dzięki temu mam lepsze poruszanie po pliku XML tak?

jeśli nie masz skomplikowanej struktury XML'a to w sumie nie musisz podpinać listenera... ale pamięci nie powinno Ci więcej zużywać przy listenerze (boć może podpinasz go kilka razy i/lub tworzysz wiele obiektów listenerów i w efekcie masz wyciek pamięci), ja opisałem ogólnie to jak ja zrobiłem a plik był dosyć rozbudowany i nieźle pozagniezdrzany, więc musiałem wiedzieć, gdzie w danym momencie jestem, który raz dany tag jest otwierany i na jakim zagłębieniu... nie podawałem żadnej metody ;]

możesz wrzucić w sumie tamten kod co Ci zjada pamięć...
Go to the top of the page
+Quote Post
duch4ever
post
Post #5





Grupa: Zarejestrowani
Postów: 155
Pomógł: 0
Dołączył: 22.06.2010

Ostrzeżenie: (0%)
-----


O wycieku raczej nie mam mowy to wręcz tutorialowy skrypt z jedną pętlą wypisującą kolejne tagi. Przypuszczam że tak to ma działać że pobiera do pamięci cały plik, pobierało dokładnie 40MB czyli tyle ile waży XML.

Nie ważne, zapewne niezależnie z jakiej metody skorzystam czas dostępu będzie podobny. Chyba muszę pomyśleć o cachowaniu, może dobrym pomysłem będzie najpierw zapisanie całego pliku do bazy a następnie odczyt już z bazy po 10 wierszy niż otwierać plik i pobierać z pliku 10 pozycji? Dodam że skrypt wymaga też pobrania zdjęć z linków w pliku xml więc po więcej niż 10 się nie da.
Go to the top of the page
+Quote Post
zegarek84
post
Post #6





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

Ostrzeżenie: (0%)
-----


Cytat(duch4ever @ 26.11.2012, 23:32:16 ) *
Przypuszczam że tak to ma działać że pobiera do pamięci cały plik, pobierało dokładnie 40MB czyli tyle ile waży XML.

Pobiera dokładnie tyle ile chcesz by pobrało... no luknij dobrze chociaż na przykład z manuala:
http://www.php.net/manual/en/example.xml-structure.php
a dodatkowo na parametry funkcji xml_parse, a jeśli dane pobrałeś przez file_get_contents to już tylko Twoja sprawa ;]

luknij jeszcze na temat:
[PHP]parsowanie pliku txt, Jak odczytać wybrany zakres linii z pliku txt, choć nie programuję zawodowo to wiem o co chodzi...
Go to the top of the page
+Quote Post
darko
post
Post #7





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


40 MB to jeszcze nie jest jakiś mega zbiór, jeżeli masz możliwość wykonania load data infile w mysql, to polecam przekonwertować xml do formatu csv, a później już pójdzie z górki.
Go to the top of the page
+Quote Post
duch4ever
post
Post #8





Grupa: Zarejestrowani
Postów: 155
Pomógł: 0
Dołączył: 22.06.2010

Ostrzeżenie: (0%)
-----


Sprawdziłem i w tym przypadku odczyt jest szybszy starym sposobem (1.2s kontra 1.8s), co do pamięci żeczywiście z rozępdu załadowałem cały plik.

Czy SplFileObject będzie działać dobrze z plikami XML? Z tego co wyczytałem jest to świetne ale do plików CSV i czytania linii z pliku.
40MB to nie dużo ale operacji jest później sporo, pobieranie grafik itp.

Ten post edytował duch4ever 27.11.2012, 20:27:47
Go to the top of the page
+Quote Post
zegarek84
post
Post #9





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

Ostrzeżenie: (0%)
-----


Cytat(duch4ever @ 27.11.2012, 20:26:32 ) *
Czy SplFileObject będzie działać dobrze z plikami XML? Z tego co wyczytałem jest to świetne ale do plików CSV i czytania linii z pliku.

przecież jeśli z niego nie chcesz korzystać to masz strukturalne odpowiedniki metod tej klasy jak fopen itd... tamta klasa służy tylko do odczytu/zapisu pliku, sam XML musisz inaczej odczytywać... tzn w większości przypadków funkcje współpracują i jeśli wiesz, od której linii chcesz kontynuować to możesz do niej przewinąć od razu...

a co do szybkości to na prawdę wszystko zależy od tego jak to masz zrobione...
Go to the top of the page
+Quote Post
cudny
post
Post #10





Grupa: Zarejestrowani
Postów: 387
Pomógł: 66
Dołączył: 31.03.2005
Skąd: Kielce

Ostrzeżenie: (0%)
-----


Ehh... tak na prawdę można się spierać nad szybkością, wydajnością i w ogóle.
Tak na prawdę trzeba sobie zadać podstawowe pytanie - po co Ci to jest ?
Bo jeśli jest to z hurtowni i masz taki plik powiedzmy raz na dobę i tylko zbierasz dane u siebie na serwerze w jakiś niecnych celach to puki co nie ruszaj tego i tyle.
Jeśli jednak będziesz tymi danymi obracał całą dobę i potem uzupełniał dane nowym plikiem xml to odpal sobie wszytko z cron'a i zaczytuj do bazy danych - serwer nawet tego nie poczuje jak zrobisz to w godzinach nocnych.
A obrazy zrzuć normalnie na dysk serwera i zaczytaj ścieżki do bazy.

Zanim pomyślisz jak te dane przetworzyć najwydajniej, zadaj sobie pytanie jak je będziesz wykorzystywał.
Go to the top of the page
+Quote Post
duch4ever
post
Post #11





Grupa: Zarejestrowani
Postów: 155
Pomógł: 0
Dołączył: 22.06.2010

Ostrzeżenie: (0%)
-----


Cytat
w większości przypadków funkcje współpracują i jeśli wiesz, od której linii chcesz kontynuować to możesz do niej przewinąć od razu

Nie rozumiem do końca, wiem że mogę przwinąć do lini ale w xml nie ma takiej struktóry jak csv (jedna linia to nie jedna "pozycja").

Cytat
Ehh... tak na prawdę można się spierać nad szybkością, wydajnością i w ogóle.
Tak na prawdę trzeba sobie zadać podstawowe pytanie - po co Ci to jest ?

Chodzi mi sam początek czyli odczyt danych z pliku, reszta jest gotowa.

CRONem nic nie zdziałam, dodanie jednej pozycji można sobie wyobrazić jak INSERT do 10 tabel i pobrani 10 zdjęć przez file_get_contents więc po 20 produktach jest time_limit w PHP i koniec (przypomnę że plik to prawie 20 000 pozycji). Dlatego musi być ajax do tego.

Ale już chyba mam najszybsze rowzianie, jeśli macie jeszcze jakieś sugestie proszę pisać.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.08.2025 - 05:27