Gribo
30.11.2010, 16:11:37
Witam
mam taki problem próbuję wygenerować sobie wielką mapę strony. jedna tabela w bazie ma ponad 150 tysięcy rekordów.
Problem jest taki że pobieram w jednym zapytaniu to wszystko następnie chce pobrać inne rekordy z innej tabeli około 30 i wywala przepełnienie pamięci (memory_limit). dlaczego Propel nie zwalnia użytej pamięci w pierwszym zapytaniu ? Próbowałem na wszystkie sposoby to jakoś wyczyścić i nic unset() nie działa, ręce już mi opadają.
Nawet jak próbuję pobierać rekordy po kilka tysiaków to dochodzi do tego momentu że wywala błąd memory_limit.
Mephistofeles
30.11.2010, 17:56:41
Wszystko hydrujesz jako obiekty?
Gribo
1.12.2010, 10:05:19
nie z obiektów zrezygnowałem i pobieram jako tablice tylko jedną kolumnę slug która mi jest potrzebna do budowania linków
Może dlatego, że wszystko dzieje się w ramach jednego skryptu? Domyślnie zapewne pamięć nie jest zwalniana do czasu zakończenia skryptu, przez co pamięć powoli się zapełnia i w pewnym momencie dochodzisz do limitu. Nie wiem jak ma to rozwiązane symfony, bo tego FW nie używam, ale zapewne masz odpowiednik takich funkcji jak mysql_free_result, które zwalniają pamięć przydzieloną do resource. Myślę, że to w połączeniu z porcjowaniem wyników powinno pomóc przy rozwiązaniu problemu
Gribo
1.12.2010, 12:01:00
A czy jest takie coś w Propelu bo jakoś przewróciłem cały internet i nie widzę nic podobnego
Quadina
1.12.2010, 14:05:16
Oczywiście, że jest zarówno w Propel jak i w Doctrine. Obiekty typu sfPropelPager() albo sfDoctrinePager() w dokumentacji znajdziesz dokładnie wszystko. Zmieniasz tylko stronę w pętli na kolejną i wykonujesz $pager->init(); kolejny raz. Pager sam zadba o zwolnienie poprzednich danych.
ALE!
Propel i Doctrine mają jedną i tę samą wadę - przepełniają pamięć hydrując wszystko. Polecam mniej joinować i wybierać jedynie te kolumny, które są potrzebne. Jeżeli i to nie pomoże to przy generowaniu sitemap możesz oczywiście zrobić skrypt który będzie redirectował do siebie przy następnej paczce danych, ale to już hardcorowe rozwiązanie
Gribo
1.12.2010, 17:37:34
problem w tym ze pobieram tylko jedną kolumnę z tabel bez joinów itp. a i tak pamięć wykorzystana to 198 mega

! i z każdym zapytaniem rośnie.
destroyerr
1.12.2010, 18:01:20
Możesz wyjaśnić dlaczego otagowałeś temat jako symfony? Możesz podać z jakiej wersji Propela korzystasz i jak pobierasz dane?
Gribo
1.12.2010, 19:28:39
Cytat(destroyerr @ 1.12.2010, 18:01:20 )

Możesz wyjaśnić dlaczego otagowałeś temat jako symfony? Możesz podać z jakiej wersji Propela korzystasz i jak pobierasz dane?
proszę cię bardzo :
Propel: 1.4
Symfony 1.4.8
$c = new Criteria();
$c->addSelectColumn($column);
$dane = FirmaPeer::doSelectStmt($c);
inne operacje
wykonuje to sobie w pętli na kilku tabelach chyba z 6. 2 z tych tabel mają po 150 tysięcy wierszy. Wyciagam tylko po 1 kolumnie z każdej tabeli.
destroyerr
2.12.2010, 19:32:05
Wrzuciłem Twój kod do pętli i dostosowałem do swoich klas. Przed pętlą "zainicjowałem" Propela i mierzyłem użycie pamięci tylko dla pętli.
Wynik jest taki, że liczba iteracji nie wpływała na zużycie pamięci. Czyli pewnie coś w tych innych operacjach robisz tak, że PHP nie daje rady z wyczyszczeniem pamięci.
Quadina
2.12.2010, 19:32:10
Dla Twojego przykładu nie widzę innej opcji jak użycie sfPropelPager. Porcjowanie danych powinno zniwelować problem braku pamięci.
phpion
2.12.2010, 19:45:33
Wydaje mi się, że szukacie problemu w złym miejscu. Problemem może być to, że pobrane dane podczas iteracji zapisujesz np. do jakiejś tablicy, na podstawie której później budujesz mapę strony. Niestety nie pokazałeś co siedzi w kodzie w miejscu "inne operacje" więc to tylko mój domysł. Pakujesz kolejne elementy (może obiekty), które systematycznie zapychają pamięć.
Gribo
3.12.2010, 13:52:14
Cytat(phpion @ 2.12.2010, 19:45:33 )

Wydaje mi się, że szukacie problemu w złym miejscu. Problemem może być to, że pobrane dane podczas iteracji zapisujesz np. do jakiejś tablicy, na podstawie której później budujesz mapę strony. Niestety nie pokazałeś co siedzi w kodzie w miejscu "inne operacje" więc to tylko mój domysł. Pakujesz kolejne elementy (może obiekty), które systematycznie zapychają pamięć.
chyba masz rację z tego całego skupienia się na optymalizacji propela zapomniałem że przecież ja cały czas powiększam tablice i to może być wina tego że mi wywala błędy
Właśnie dlatego napisali tu chyba niemal wszyscy o zwalnianiu zasobów

Zwalniałeś zasoby, które przychodziły z bazy, ale zapomniałeś o zasobach/zmiennych samego skryptu. No cóż... każdy ma chwile zaćmienia. Ja dziś na przykład zgłupiałem i ostatecznie z kumplem znaleźliśmy błąd skryptu w miejscu nieprzewidzianym... Tworzyłem AJAX, który miał posłać do skryptu datatable formularz, a więc elementy z polami miały atrybuty i musiałem uważać z obydwoma rodzajami apostrofów zanim całość potraktowałem funkcją json_encode. Użyłem htmlentities jak zawsze w wypadku ucieczki w value dla znaków specjalnych i... dostałem w wyniku nulla. Przez pół godziny ponad się motałem i sprawdzałem wszystko po kolei zanim doszedłem, że owa funkcja robi mi krecią robotę. Dopiero jej zmiana na htmlspecialchars sprawiła, że całość zadziałała. Kolejne punkty expa w webmasterce zaliczone )
Gribo
3.12.2010, 21:40:00
a używałeś fiddler do śledzenia ajaxa mi to niesamowicie uproszcza robotę
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę
kliknij tutaj.