Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Optymalizacja kodu
Forum PHP.pl > Forum > PHP
boro11
Witam!
Mam kod, który działa tak jak miał działać - tj. wykonuje wszystkie czynności jakie ma robić. Niestety obciąża mi serwer dosyć znacznie i spowalnia strony. Z indeksu przeniosłem go do jednej z podstron i trochę się poprawiło ale ta podstrona teraz działa wolno.

Oto kod:

  1. $sites = array();
  2. $limits = array();
  3. $count = array();
  4. $zap=array(1 => 'SELECT',2 => 'nazwa, limits',3 => 'FROM',4 => 'test_site');
  5. $query = $db->zap($zap);
  6.  
  7. while ($row = mysql_fetch_array($query))
  8. {
  9. $sites [$row['nazwa']] = $row['nazwa'];
  10. $limits [$row['nazwa']] = $row['limits'];
  11. $count [$row['nazwa']] = 0;
  12. }
  13.  
  14. $zap2=array(1 => 'SELECT',2 => 'site',3 => 'FROM',4 => 'test_sites',5 => 'WHERE ((status = "Approved") OR (status = "Pending"))');
  15. $quer = $db->zap($zap2);
  16. while ($row2 = mysql_fetch_array($quer))
  17. {
  18. if (in_array($row2['site'],$sites)) $count[$row2['site']]++;
  19.  
  20. if (($count[$row2['site']] > $limits[$row2['site']]) && ($limits[$row2['site']] != '~') && ($limits[$row2['site']]!='') && ($limits[$row2['site']]!='0'))
  21. {
  22. $zap3=array(1 => 'UPDATE',2 => 'test_site',3 => 'SET',4 => 'status="LIMITED"',5 => 'WHERE ((nazwa="'.$row2['site'].'") AND (status<>"SCAM"))');
  23. $db->zap($zap3);
  24. }
  25. }
  26.  
  27. $zap=array(1 => 'SELECT',2 => 'nazwa, limits',3 => 'FROM',4 => 'test_site');
  28. $query2 = $db->zap($zap);
  29. while ($row2 = mysql_fetch_array($query2))
  30. {
  31. if (isset($count[$row2['nazwa']])) $put = $count[$row2['nazwa']].'/'.$row2['limits'];
  32. else $put = '0/'.$row2['limits'];
  33. $zap=array(1 => 'UPDATE',2 => 'test_site',3 => 'SET',4 => 'refkow = "'.$put.'"',5 => 'WHERE nazwa="'.$row2['nazwa'].'"');
  34. $db->zap($zap);
  35. }


Dałoby się to jakoś zoptymalizować lub zrobić żeby robiło się np. raz na 10 minut, a nie z każdym wczytaniem strony?
SmokAnalog
Co ten kod robi dokładnie? Nie jest na tyle czytelny, żeby chciało mi się go analizować.

Jeśli chodzi o optymalizację, to upewnij się, że pole `status` ma typ ENUM (a nie VARCHAR) i że masz indeks na polu `nazwa`. Domyślam się, że masz dużo rekordów w tej tabeli.
boro11
W tabeli test_sites jest obecnie 24000 rekordów (liczba ta rośnie dosyć szybko) - zmieniłem już na enum dziękuję za radę.
W tabeli test_site jest 1400 rekordów - indeksu nie mogę dodać bo mam pole ID, które ma autoinkrementacje i mi wywala błąd

Kod zarządza kategoriami stron dodanych do mojej strony. Sprawdza czy został zapełniony limit użytkowników którzy się zapisali

stąd:

  1. $put = $count[$row2['nazwa']].'/'.$row2['limits'];


nazwa to ilość zapisanych / limits to liczba określona przez nas

Jeśli liczby się wyrównają to strona jest przenoszona do innej kategorii:

  1. $zap=array(1 => 'SELECT',2 => 'nazwa, limits',3 => 'FROM',4 => 'test_site');
  2. $query2 = $db->zap($zap);
  3. while ($row2 = mysql_fetch_array($query2))
  4. {
  5. if (isset($count[$row2['nazwa']])) $put = $count[$row2['nazwa']].'/'.$row2['limits'];
  6. else $put = '0/'.$row2['limits'];
  7. $zap=array(1 => 'UPDATE',2 => 'test_site',3 => 'SET',4 => 'refkow = "'.$put.'"',5 => 'WHERE nazwa="'.$row2['nazwa'].'"');
  8. $db->zap($zap);
  9. }
SmokAnalog
Chodzi o indeks, a nie klucz podstawowy. Indeksy znacznie przyśpieszają wyszukiwanie po danym polu. ZNACZNIE! smile.gif
boro11
Okej ustawiłem indeks i rzeczywiście jest już szybciej o całe 4 sekundy, ale nadal trwa to długo bo ~3 sekund, nawet trochę więcej.

Opisałe kod w poście wyżej smile.gif

Edit: Czy dodanie tego indeksu do pola status pomoże?
epg.kojak
Jeśli nie jest dla ciebie problemem, żeby ta tablica była generowana raz na 10 minut, to zrób skrypt, który wygeneruje ci taką tablicę i zapisze w pliku i ustaw w CRONie żeby skrypt był uruchamiany co 10 minut. Nie będziesz użytkownika obciążał skomplikowanymi algorytmami.
Olbrych
Robisz kilka pętli i w nich zapytania. Jeżeli masz bardzo dużo rekordów to robisz masakrycznie dużo updatów. Musisz to przepisać w sql i robić update za jednym zamachem wszystkiego bo inaczej nie ma szans na szybkie działanie.
Zrób echo wszystkich zapytań to będzie lepiej widać jak można to napisać.
zegarek84
skoro update robisz w pętli i jest on zależny od zewnętrznego zapytania to wystarczyło by, gdybyś ten update robił w jednej transakcji na całą pętlę, poczytaj o tym...

oprócz tego pierwszą pętlę z UPDATE możesz załatwić w jednym zapytaniu gdyż zmienia się tylko warunek WHERE a reszta jest statyczna
SQL IN Operator
drugi update to już raczej trzeba zacząć transakcję przed pętlą i zakończyć za pętlą...

choć jeszcze to Ci się nie przyda, ale np. ja problem z aktualizacją wielu danych z plików XML (sporych więc parsowałem te pliki nie przez DOM a SAX) gdzie czasami trzeba było dodać nowe rekordy rozwiązałem w ten sposób, iż tworzyłem tabelę tymczasową identyczną i w transakcji robiłem insert, po czym zapytanie gdzie id się powtarzało (nie mam tam autoinkrementacji - można to dać też na inne unikalne rekordy) robiłem jednym zapytaniem UPDATE from SELECT , kolejnym insert from select, a kolejnym usuwałem tabelę tymczasową...
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.
Invision Power Board © 2001-2025 Invision Power Services, Inc.