Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: optymalizacja skryptu - pomocy
Forum PHP.pl > Forum > PHP
yalus
witam

posiadam w bazie danych tebele o nazwie global w ktorej przechowywane sa informacje na temat ksiazek, znajduje sie tam kilka tysiecy pozycji.

tabela ta ma taka oto strukture:

tabela global:
| id | tytul | id_autor | id_category | .......... i pozostale pola

tabela autor:
| id | autor |

tabela category:
| id | category |

normalne jest ze w tej tabeli moze znajdowac sie wiecej niz jedna pozycja tego samego autora (ten sam autor kilka innych tytulow) oraz to ze znajduja sie wiecej niz jedna kategoria np. horror, przygoda

np:
autor_1 | tytul_10 | category_1
autor_1 | tytul_11 | category_1
autor_1 | tytul_12 | category_1
autor_1 | tytul_13 | category_1
autor_1 | tytul_14 | category_1
autor_2 | tytul_21 | category_2
autor_2 | tytul_22 | category_2
autor_3 | tytul_31 | category_2
autor_3 | tytul_32 | category_2
autor_4 | tytul_41 | category_1
autor_4 | tytul_42 | category_1
autor_5 | tytul_51 | category_3
autor_5 | tytul_52 | category_3


szukam rozwiazania aby wypisac wszystkich autorow pisszacych w tej samej kategorii tematycznej:

tzn klikajac na link: category_1

otrzymalbym cos takiego:

KATEGORIA: category_1
liczba autorow w tej kategorii: 2
liczba ksiazek w tej kategorii: 7


oraz liste autorow:

autor_1 (5)
autor_4 (2)



napisalem skrypt ktory realizuje to zadanie ale wysypuje sie gdy w danej kategorii jest duza liczba autorow: np kategoria science-fiction gdzie jest samych autorow 2tys kazdy autor napisz chodzby dwie ksiazki to juz jest 4tys pozycji:

skrypt nie radzi sobie z czasem wykonania (chyba) dostaje taki oto komunikat:


Fatal error: Maximum execution time of 30 seconds exceeded in search.php on line ...


oto skrypt:

  1. <?php
  2. $link=mysql_connect (hostTxt,userTxt,passTxt);
  3. mysql_select_db (bazaTxt);
  4.  
  5. //zmienna $_GET['category'] wchodzi do skryptu informujac o ktora kategorie chodzi
  6.  
  7. $zapytanie = "SELECT * FROM category WHERE id='".$_GET['category']."'";
  8. $wykonaj = mysql_query ($zapytanie) or die(mysql_errno() . ": " . mysql_error(). "\n");
  9. $wiersz=mysql_fetch_array($wykonaj);
  10. $kategoria=$wiersz['category'];
  11. //w powyzszym zapytaniu pobieram nazwe kategorii
  12.  
  13.  
  14. $zapytanie = "SELECT * FROM global WHERE id_category='".$_GET['category']."'";
  15. $wykonaj = mysql_query ($zapytanie) or die(mysql_errno() . ": " . mysql_error(). "\n");
  16. $i=0;
  17. while ($wiersz=mysql_fetch_array($wykonaj))
  18. {
  19. $wejscie[]=$wiersz['id_autor'];
  20. $i++;
  21. }
  22. //w powyzszym zapytaniu laduje wszystkich autorow piszacych w jednej kategorii to 
    tablicy $wejscie[]
  23. //moze zdazyc sie tak ze jeden autor napisal wiecej niz jedna ksiazke w tej samej 
    kategorii
  24.  
  25.  $wynik = array_unique ($wejscie);
  26.  
  27. //dlatego z tablicy $wejscie trzeba usunac powtarzajacych sie autorow
  28.  
  29.  $ile_akt=0;
  30.  $suma_poz=0;
  31. //powyzsze zmienne beda odpowiedzialne za wyswietlenie szczegolow o kategorii
  32. //$ile_akt - ile autorow jest w danej kategorii
  33. //$suma_poz - ile jest ksiazek nalezaczych do jednej kategorii
  34.  
  35.  
  36. //czesc realizujaca glowne zadanie skryptu
  37. foreach ($wynik as $klucz => $wartosc)
  38. {
  39. $zapytanie = "SELECT * FROM authors WHERE id='".$wartosc."'";
  40. $wykonaj = mysql_query ($zapytanie); or die(mysql_errno() . ": " . mysql_error(). "\n");
  41. $wiersz=mysql_fetch_array($wykonaj);
  42. $autor=$wiersz['autor'];
  43. //w powyzszym zapytaniu pobieram nazwe pierwszego autora z zadanej kategorii
  44.  
  45. //w tym zapytaniu pbieram liczbe tytulow ksiazek nalezacych do zadanej kategorii i
     napisanych przez danego autora
  46. $zapytanie = "SELECT * FROM global WHERE id_autor='".$wartosc."' and id_category='".$_GET['category']."'";
  47. $wykonaj = mysql_query ($zapytanie); or die(mysql_errno() . ": " . mysql_error(). "\n");
  48. $i=0;
  49. while ($wiersz=mysql_fetch_array($wykonaj))
  50. {
  51. $i++;
  52. }
  53. $suma_poz=$suma_poz+$i;
  54. echo"<tr><td><a class=menu_link href=details.php?id=".$wartosc."&cat=".$_GET['category'].">".$autor." (".$i.")</a></td></tr>";
  55.  
  56.  $ile_akt++;
  57.  }
  58.  
  59. // a tutaj wypisuje szczegoly na temat danej zadanej kategorii 
  60. echo"<div>
  61.  <span>Category: ".$kategoria."</span></br>
  62.  <span>Total authors in this category: ".$ile_akt."</span></br>
  63.  <span>Total books in this category: ".$suma_poz."</span>
  64. </div>";
  65.  
  66. ?>



wg powyzszego przykladu blad ten mi sie pojawia
w lini 40 i 47
Fatal error: Maximum execution time of 30 seconds exceeded in search.php on line 40
lub
Fatal error: Maximum execution time of 30 seconds exceeded in search.php on line 47

czy moze mi ktos pomoc nie wiem o co chodzi
czy tern skrypt dziala w nieskonczonosc?,
petla nigdy sie nie konczy?
czy jeszcze cos innego
ja nie mam juz pomyslow

a moze ktos mi podsunie inny sposob rozwiazania tego problemu

pozdrawiam

ps. wiem ze ta tabel nie ma jeszcze nic wspolnego z postacia normalna ale teraz nie ma to najmniejzszego znaczenia
nospor
o moj ty swiecie.... smile.gif
a o left join lub o zwyklym pobieraniu danych z kilku tabel w jednym zapytaniu slyszal? Przejrzyj se przyklady lef joina, poczytaj o tym, a potem bedziesz mogl polaczyc to zapytanie:

  1. <?php
  2.  $zapytanie = "SELECT * FROM category WHERE id='".$_GET['category']."'";
  3. ?>

z ta petla generujaca x zapytan:
  1. <?php
  2. foreach ($wynik as $klucz => $wartosc)
  3. {
  4. $zapytanie = "SELECT * FROM authors WHERE id='".$wartosc."'";
  5.  ?>

to wszystko w jednym zapytaniu da sie zrobic

nastepnie:
  1. <?php
  2. $zapytanie = "SELECT * FROM global WHERE id_autor='".$wartosc."' and id_category='".$_GET['category']."'";
  3.   $wykonaj = mysql_query ($zapytanie); or die(mysql_errno() . ": " . mysql_error(). "\n");
  4.   $i=0;
  5.   while ($wiersz=mysql_fetch_array($wykonaj))
  6.     {
  7.     $i++;
  8.     }
  9. ?>
pobierasz x wierszy tylko po to by zwikeszac licznik o jeden? mysql_num_rows(). ale to i tak zle rozwiazanie. Poczytaj o count w mysql
pozatym tę ostatnia petle tez mozna podpiac do zapytania, o ktorym pisalem wczesniej. poczytaj o group by
Tyle na szybko. zycze milej lektury winksmiley.jpg
yalus
ok dzieki,

ale abstrachujac juz od techniki programownia - wiem ze nie jest najlepsza, ciagle sie ucze

dlaczego wystepuje ten blad

tak na chlopski rozum powinno to przeleciec cala tabele i wypluc wyniki
nospor
no ale ty przeczytales ten blad? wyraznie ci napisalo, ze skonczyl sie czas na skrypt. ten czas jest ustawiany w php.ini
a skrypt sie wykonuje dlugo, bo masz w nim zero optymalnosci, co juz w poscie wyzej wyjansilem smile.gif
yalus
kapuje,


no coz trzeba bedzie zwiekszyc czas na wykonanie skryptu winksmiley.jpg
kszychu
Cytat(yalus @ 2006-05-12 12:18:02)
kapuje,


no coz trzeba bedzie zwiekszyc czas na wykonanie skryptu winksmiley.jpg

blink.gif snitch.gif jerry.gif
Ale najciekawsze jest to, że ani razu nie zapytał: 'a jak to zoptymalizować? Może pomożecie?'
Cenię ludzi samodzielnych, którzy po swojemu rozwiązują problemy. cool.gif
yalus
Cytat(kszychu @ 2006-05-12 11:34:29)
Ale najciekawsze jest to, że ani razu nie zapytał: 'a jak to zoptymalizować? Może pomożecie?'

1- zerknij na temat posta

2 -
Cytat
czy moze mi ktos pomoc nie wiem o co chodzi
czy tern skrypt dziala w nieskonczonosc?,
petla nigdy sie nie konczy?
czy jeszcze cos innego
ja nie mam juz pomyslow

a moze ktos mi podsunie inny sposob rozwiazania tego problemu
kszychu
Widzisz, chodziło mi o to, że zwiększenie czasu wykonania skryptu nie jest żadnym rozwiązaniem. Problem leży w wielu niepotrzebnych zapytaniach, które niejednokrotnie można zastąpić jednym. Ale o tym wszystkim powiedział Ci już nospor, a Twoim komentarzem było to, że zwiększysz czas.
yalus
oczywiscie to byl zart,
zdaje sobie sprawe ze nie jest to zadne rozwiazanie

rozumiem dokladnie o co chodzi

ok poprawilem nieco czas
a to zapytanie ktore uzylem jest chyba jednoznaczne z join'em

  1. <?php
  2. foreach ($wynik as $klucz => $wartosc)
  3.  {
  4. $zapytanie = "SELECT * FROM authors, global WHERE authors.id=global.id_autor and authors.
    id='"
    .$wartosc."' and global.id_category='".$_GET['category']."'";
  5. $wykonaj = mysql_query ($zapytanie) or die(mysql_errno() . ": " . mysql_error(). "\n");
  6. $wiersz=mysql_fetch_array($wykonaj);
  7. $autor=$wiersz['autor'];
  8. }
  9.  
  10. ?>

(czas sie poprawil znacznie ale dalej 30sek to nie wystarczajaco)

wyzucilem drugie zapytanie generujace liczbe pozycji ale na moim poziomie zaawansowania nie jestem w stanie wyobrazic sobie jak pozbyc sie petli for each generujacej zapytania.

to co pomozecie?
kszychu
Cytat(yalus @ 2006-05-12 12:58:02)
nie jestem w stanie wyobrazic sobie jak pozbyc sie petli for each generujacej zapytania.

  1. <?php
  2. $zapytanie = "... WHERE id IN (".implode(',', $wynik).")".
  3. ?>
yalus
o w morde!! to working
nigdy bym tego nie przeskoczyl.
thumbsupsmileyanim.gif

dzieki serdeczne

masz u mnie browara party.gif
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.