Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dziwne zachownie skryptu przy zapytaniach MySQL
Forum PHP.pl > Forum > PHP
ongaqjin
Nie zauwazylem nigdzie odpowiedzi na moj problem, wiec zakladam ten temat. Problem mam nastepujacy. Napisalem strone, ktora pobiera dane z bazy MySQL (chodzi o logi z monitorowania roznych stron, wiekszosc logow jest wykonywana co minute, wiec jest ich dosc duzo). Skrypt pobiera wszystkie logi od polnocy dnia dzisiejszego do chwili obecnej i dla kazdej strony zlicza srednia czasu odpowiedzi. Dodatkowo na stronie znajduje sie maly formularz, w ktorym mozna ustawic date poczatkowa i koncowa zestawienia. Formularz ma akcje ustawiona na ten sam plik (na siebie) a skrypt sprawdza, czy sa odpowiednie dane w $_POST i jesli nie, wyswietla standard (czyli od polnoc do chwili obecnej), jesli sa dane w $_POST, wyswietla zestawienie z uwzglednieniem podanych dat. Daty te sa umieszczone w samym zapytaniu MySQL (... where `date`>="startY-startM-startD 00:00:00" and `date`<="endY-endM-endD 23:59:59" gdzie oczywiscie zamiast startY, startM, etc. sa odpowiednie wartosci). Problem zaczyna sie, jesli chce wyswietlic zestawienie dla zbyt duzego okresu. Wtedy dla pewnej wartosci granicznej (okolo 60000 rekordow) strona wyswietla sie niepoprawnie (tzn. poczatek jest w porzadku, ale nagle sie zatrzymuje bez zadnych komunikatow). Natomiast jestli wezme jeszcze wiekszy przedzial czasowy (max. ponad 90000 rekordow, przy czym rekordy sa uzywane tylko do zliczania sredniej dla kazdej ze stron), to po kliknieciu OK w formularzu (co powinno zapisac dane do $_POST i wrocic do tej samej strony), zamiast wysiwetlenia strony czy chociaz komunikatow o bledach, otwiera mi sie okienko zapisywania pliku a sama strona sie nie otwiera. Skrypt wydaje sie byc napisany dobrze, moze ma to zwiazek z jakimis limitami narzuconymi przez PHP, POST lub moj serwer? Prosze o pomoc!
MajareQ
Hmmm... pomyślmy. Rozkazujesz wyświetlić 90,000 rekordów z bazy danych i strona przestaje działać.
Być może... powtarzam! być może obciążyłeś trochę serwer/bazę danych. (dla niewprawionych - ironia)

Może zaczniesz myśleć o optymalizacji zapytań?

Ja np. zacząłbym cachować dane które zostały zarejestrowane na ten dzień.
ongaqjin
No wlasnie problem w tym, ze ja nie wyswietlam tych danych. Zapytanie do bazy danych ma na celu tylko pobranie wartosci czasu odpowiedzi do zliczania sredniej. Poza tym, zazwyczaj jesli obciazam zbytnio serwer, skrypt wykonuje sie do momentu przeciazenia i staje, albo wyrzuca blad np. o zbyt duzej ilosci zaalokowanej pamieci. A tutaj skrypt nawet nie probuje sie wykonac, bo zamiast wyswietlic ta strone otwiera mi okienko zapisywania pliku. Jakies inne pomysly? Oto skrypt:
  1. <div class="header"><?php echo $this->mod->translate('Response time comparison',$this->ln);?></div>
  2. <br />
  3. <form action="http://<?php echo $_SERVER['SERVER_NAME'];?>/index.php/index/index/<?php echo $this->ln;?>/comparison" method="POST">
  4. <table border="0">
  5. <tr><th></th><th><?php echo $this->mod->translate('Year',$this->ln);?></th><th><?php echo $this->mod->translate('Month',$this->ln);?></th><th><?php echo $this->mod->translate('Day',$this->ln);?></th><th></th><th><?php echo $this->mod->translate('Year',$this->ln);?></th><th><?php echo $this->mod->translate('Month',$this->ln);?></th><th><?php echo $this->mod->translate('Day',$this->ln);?></th><th></th></tr>
  6. <tr><th><?php echo $this->mod->translate('From:',$this->ln);?></th><td><select name="yearF">
  7. <?php for($i=2008;$i<=(date('Y')+0);$i++) echo '<option>'.$i;?></select></td><td><select name="monthF">
  8. <?php for($i=1;$i<=12;$i++) echo '<option>'.$i;?></select></td><td><select name="dayF">
  9. <?php for($i=1;$i<=31;$i++) echo '<option>'.$i;?></select></td><th><?php echo $this->mod->translate('To:',$this->ln);?></th><td><select name="yearT">
  10. <?php for($i=2008;$i<=(date('Y')+0);$i++) echo '<option>'.$i;?></select></td><td><select name="monthT">
  11. <?php for($i=1;$i<=12;$i++) echo '<option>'.$i;?></select></td><td><select name="dayT">
  12. <?php for($i=1;$i<=31;$i++) echo '<option>'.$i;?></select></td><td><input type="submit" value="OK"></input></td></tr>
  13. </table>
  14. </form>
  15. <?php
  16. $startDate=date('Y-m-d').' 00:00:00';
  17. $endDate=date('Y-m-d').' 23:59:59';
  18. if(array_key_exists('yearF',$_POST)){
  19.    $startDate=$_POST['yearF'].'-'.$_POST['monthF'].'-'.$_POST['dayF'].' 00:00:00';
  20.    $endDate=$_POST['yearT'].'-'.$_POST['monthT'].'-'.$_POST['dayT'].' 23:59:59';
  21. }?>
  22. <b><?php echo $this->mod->translate('Since',$this->ln).': '.$startDate.' '.$this->mod->translate('To:',$this->ln).' '.$endDate;?></b>
  23. <table width="100%" border="0">
  24. <?php $query=$this->db->query('select * from sites');
  25. foreach($query->result() as $site){
  26.    echo '<tr><th style="text-align:right">'.$site->address.' </th><td>';
  27.    $rsp=0;
  28.    $count=0;
  29.    $query2=$this->db->query('select * from pages where `site`='.$site->id_site);
  30.    foreach($query2->result() as $page){
  31.        $query3=$this->db->query('select * from logs where `page`='.$page->id_page.' and `date`>="'.$startDate.'" and `date`<="'.$endDate.'"');
  32.        foreach($query3->result() as $log){
  33.            $rsp+=$log->response;
  34.            $count+=1;
  35.        }
  36.    }
  37.    if($count==0) echo $this->mod->translate('No logs available',$this->ln);
  38.    else{
  39.        $avgRsp=(int)($rsp/$count);
  40.        if($avgRsp>=0){
  41.            echo '<div style="background:#5353a8; width:'.($avgRsp*4).'px">';
  42.            echo $avgRsp.'ms';
  43.        }else{
  44.            echo '<div style="background:#ff0000">'.$this->mod->translate('No response',$this->ln);
  45.        }
  46.        echo '</div>';
  47.    }
  48.    echo '</td></tr>';
  49. }?>
  50. </table>


Ten skrypt to plik comparison.php wlasnie (URL ma taka postac, poniewaz uzywam CodeIgnitera), wiec teoretycznie po kliknieciu OK powinna wyswietlic sie ta sama strona z nowymi danymi. I tak sie dzieje, jesli wybiore odpowiednio maly zakres czasu lub uzyje domyslnego. Zrozumialbym przeciazenie serwera, ale czy moze objawiac sie to w taki sposob, ze po kliknieciu linka (w innym miejscu aplikacji mam ten sam problem z linkiem zamiast przycisku wiec to zadna roznica) zamiast otworzyc strony czy wyswietlic bledu, otwiera sie okienko zapisywania pliku? (juz kompletnie inna sprawa jest fakt, ze plik, ktory rzekomo "chcialbym" zapisac ma nazwe odpowiadajaca ostatniemu czlonowi URL skryptu action formularza a po zapisaniu jest kompletnie pusty i bez rozszerzenia)
nospor
1) zeby zliczyc rekordy, policzyc srednia - pobierasz wszystkie rekordy. No faktycznie, nie obciązasz serwera
Takie rzeczy robi sie na poziomie mysql anie na poziomie php

2)zapytania w petli - kolejny bol

3)
Cytat
ze po kliknieciu linka (w innym miejscu aplikacji mam ten sam problem z linkiem zamiast przycisku wiec to zadna roznica) zamiast otworzyc strony czy wyswietlic bledu, otwiera sie okienko zapisywania pliku
Tak reaguja czasem przegladarki gdy strona sie wywala
ongaqjin
Zmienilem zapytania sql i wszystko fruwa smile.gif. Jestem swiezy w php, stad moje problemy z optymaliacja. Teraz mam podobny problem w innym miejscu aplikacji i tym razem brakuje mi juz pomyslow, jak to zoptymalizowac.
Otoz potrzebuje wypisac wszystkie logi z podanego zakresu czasu do pliku txt. Dla kazdego przetwarzanego loga dodatkowo musze pobrac info o stronie z innej tabeli (bo w logu mam zapisane tylko ID strony) i dodatkowo pobrac info o portalu z kolejnej tabeli (w info o stronie mam ID portalu, do ktorego nalezy). Tym razem nie bardzo mam mozliwosc zoptymalizowania zapytania SQL o logi, bo tak czy inaczej musze pobrac je wszystkie a potrzebuje rowniez wszystkich danych zapisanych w tych logach (czyli nie moge zmniejszyc ilosci pobieranych kolumn). Czy jest moze jakas konkretna technika, ktorej moglbym tu uzyc, zeby to dzialalo? W tej chwili oczywiscie skrypt nie wykonuje sie do konca, bo konczy sie pamiec do alokacji. Wyglada to mniej wiecej tak:
Pobierz wszystkie (potrzebne) logi;
Dla kazdego loga:
- Pobierz informaje o stronie i portalu
- zapisz informacje do pliku

Przy kazdym zapisywaniu info do pliku otwieram plik (wyczyszczony przed wykonaniem petli) fopen(plik,'a'), zapisuje info fwrite(plik,info), zamykam plik fclose(plik).
Jakies pomysly?
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.