Skocz do zawartości
zarcel

[php] Pobranie Kilku Tysięcy Rekordów Z Bazy

Rekomendowane odpowiedzi

Witam!

 

Pracujemy właśnie nad pewnym projektem i mam pewien problem. Będę potrzebował pobrać wszystkie rekordy z bazy, a zakładam, że będzie ich dużo i cośtam z każdym z nich zrobić.

Kiedyś robiłem coś podobnego i zrobiłem :

 

while(mysql_fetch_array($zapytanie)){//TUTAJ JAKIS TAM KOD}

Miałem wtedy w bazie 200 rekordów, skrypt był odpalany z crona, niestety wykonywał się tylko dla pierwszych 20 rekordów(był on dość 'duży' - łamał captche, używal curla). Moim zdaniem wykonywanie zostało ograniczone do tylu, przez zbyt długi czas wykonywania, aczkolwiek nie jestem tego pewny.

 

Jeśli ktoś ma doświadczenie z czymś takim to proszę o pomoc :)

Pomysły, kod, pseudokod, wszystko mile widziane.

Edytowane przez zarcel

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ale chcesz je wszystkie od razu obrobić? Trochę lipa, bo nie ma wtedy żadnej kontroli nad skryptem, a jak się coś wysypie, musisz zaczynać od nowa

 

Ja sobie dzieliłem skrypt czymś takim (mniej - więcej) - import z xml + update do bazy kilkunastu tysięcy produktów + zapis do innego xml

$tm0 = time();	//poczatkowy czas$timelimit = ini_get('max_execution_time');while(...) //for, foreach, niewazne- wiadomo{		//gdzies w petli ktora leci po rekordach...		if ((time()-$tm0)>=$timelimit - 5)	{$breakit = 1; set_time_limit($timelimit+20); }	//zmiana limitu czasu na "bezpieczny"	.	.	//kod petli	.	if($breakit == 1)	{		//tutaj redirect do tego samego pliku, z przekazanym elementem, na ktorym sie przerwalo (id, albo cos w tym stylu, getem, postem, albo najlepiej w tymczasowym pliku zapisanym na serwerze)		//redirect przez wywolanie prostego js, albo headera (w zaleznosci od potrzeb).	}}

Co by trzeba było zrobić, to ustawić sobie zapytanie, żeby pobierało paczkę danych od ostatniego elementu. Ewentualnie- automagiczny redirect przy każdym rekordzie w bazie i zaczęcie od kolejnego.

U mnie to działało bez pudła przez ponad rok i działa nadal. Pomijając drobiazgi jak popsuty czasem xml, z którego się importuje.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Przedewszystkim - dzięki za odpowiedź.

Niezła metoda myślałem o czymś takim, ale nigdy nie zabrałem się za zrobienie. Niestety tutaj końcowi userzy są dość poszkodowani opoźnieniem, a mi zależy żeby każdy user miał wykonany kod w jak najkrótszym czasie :P I takie pytanko, czy jak odpalam coś z crona to działa JS ?

Możesz zdradzić ile trwa wykonanie skryptu dla ilu elementów ?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

To zależy od serwera.

Ok. 20-22 tysiące produktów, każdy jeszcze max 8 zdjęć, max 30 dodatkowych atrybutów, przypisanie producenta, rabatu, kosztów transportu, liczenie ceny, etc. Ogólnie - dla pojedynczego produktu od 3 do 40 zapytań.

 

Na serwie nazwa.pl skrypt się wykonywał kilka(naście) godzin przez godzinowy limit zapytań do bazy - zapytań szło ponad 700 tysięcy i trzeba było co chwilę pauzować, aż limit się odnowi. Mają dodatkowo jakieś lamerskie połączenie miedzy sql a php i każde zapytanie to ~ćwierć sekundy lag.

Aczkolwiek, na serwerze bez tego limitu lata jak dziki i po 5-7 minutach jest po wszystkim.

Na moim localhoście (c2d, giga ramu, etc) całość trwa 10 minut.

 

Co do odpalania js z crona... jeżeli na serwerze jest zainstalowana przeglądarka która obsłuży js, to można ją odpalić z crona z adresem skryptu i powinno się wszystko przeładowywać. Jeżeli nie ma, zostają headery, albo jeszcze coś innego, na co do tej pory nie wpadłem.

Aczkolwiek... na tym moim skrypcie nauczyłem się, że nie ma rzeczy niemożliwych, więc pozostaje poszukać.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie, dlaczego?

exit bez argumentów kończy skrypt w miejscu, w którym ten exit jest. Następny skrypt, uruchomiony w kolejnej minucie, będzie już całkiem innym zadaniem (chyba).

W sumie, nie znam się na cronie na tyle dobrze, żeby dokładnie na Twoje pytanie odpowiedzieć. Bardzo rzadko był mi potrzebny, a już wcale taki uruchamiany co minutę, kiedy poprzednie zadanie może jeszcze działać. Co się wtedy stanie, po prostu nie wiem. Warto sprawdzić.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Hmm nie musze czekać aż się wykona, on się będzie wykonywał zazwyczaj kilka ms, natomiast kiedy warunek bedzie prawdziwy chcialbym zeby pobral tych userow i cos dla nich zrobil, potem sie usmiercil i usunal z crona :)

Dodam, że nie wiem jak to zrobić :D

Edytowane przez zarcel

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Rozumiem, że chcesz pobrać bardzo dużo rekordów i je obrabiać. Nie prościej pobierać i obrabiać rekordy partiami? Np po 100 rekordów?

 

SELECT * FROM baza LIMIT 0,100SELECT * FROM baza LIMIT 100,100SELECT * FROM baza LIMIT 200,100

Generalnie więc całość zamykasz w pętli while lub do-while, w warunku sprawdzasz czy wynik zapytania zwrócił chociaż jeden rekord. Jeśli tak, to wykonujesz obliczenia, potem zwiększasz limit o 100 i pętla sobie lata aż zapytanie zwróci 0 rekordów, pętla się kończy.

Wyniki możesz wyświetlać partiami w tejże pętli lub ładować do zmiennej, aby potem wyświetlić wynik końcowy lub w celu dalszej obróbki.

 

Ewentualnie walisz na początek proste zapytanie SELECT id (czy coś innego prostego) i zliczasz ilość rekordów w bazie. Następnie to samo co wyżej zamykasz w pętli FOR.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Masz możliwość edytowania swojego pliku crona i uruchamiania samego crona z poziomu php? Jeżeli tak, to dałoby się chyba skrypt wyłączyć (gdyby uprawnienia użytkowników było w porządku). Aczkolwiek- istnieje prawdopodobieństwo, że wyłączenie skryptu przez niego samego jest zbędne... nie do końca w tym momencie rozumiem jak on dokłądnie ma działać (w którymś tam miejscu się pogubiłem).

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ewentualnie walisz na początek proste zapytanie SELECT id (czy coś innego prostego) i zliczasz ilość rekordów w bazie. Następnie to samo co wyżej zamykasz w pętli FOR.

 

Za takie coś powiniem bić linijką po łapach. Może jednak lepsze jest select count(*) from tabela? Zliczanie powinno być wykonywane po stronie engine'u bazodanowego a nie po stronie aplikacji!

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

O to dokładnie mi chodziło (count), tylko nie chciało mi się grzebać w dokumentacji, jak to dokładnie leciało.

Jak ktoś sobie zadał trud użycia Google, to znalazł to rozwiązanie.

 

Znając życie to by napisał aplikację zabijającą serwer ;]

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie


×
×
  • Dodaj nową pozycję...