Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [MySQL][PHP]Optymalizacja zapytań, Po wykonaniu tej pętli przekracza mi limit 400000 zapytań na godzinę.
poczatkujaca12
post 24.06.2010, 13:35:52
Post #1





Grupa: Zarejestrowani
Postów: 107
Pomógł: 0
Dołączył: 24.06.2010
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Mam taki kod...
Niby nic skomplikowanego...
  1. $na = explode( '<br />', $r['npr']);
  2. $text .= "\r\n\r\nA poniżej przesyłamy linki do pobrania plików:\r\n";
  3. $kol=count($na);
  4.  
  5. for($i=0; $i < $kol; $i++){
  6. $nazw = explode( '<br />', $r['npr']);
  7. $nazwa=substr($nazw[$i], 0, -4);
  8. $zo1=mysql_query("select * from prod where nazwa='".$nazwa."'");
  9. while($k=mysql_fetch_array($zo1)){
  10. $z1=mysql_query("Select * from down where id_user='".$r['ius']."' and plik='".$k['plik']."'");
  11. if (mysql_num_rows($z1)!=0){
  12. mysql_query("update down set koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."' where id_user='".$r['ius']."' and plik='".$k['plik']."'");
  13. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  14. } else {
  15. mysql_query("insert into down set id_prod='".$nazwa."', id_user='".$r['ius']."', plik='".$k['plik']."', koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."'");
  16. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  17. }
  18. }
  19. }

Dodam że $kol może mieć wartość co najwyżej 3...
Więc razem powinno wygenerować max 12 zapytań.

Dlatego, że przy $kol=3 , zapytanie
$zo1=mysql_query("select * from prod where nazwa='".$nazwa."'");
też zwróci 3 rekordy

Więc za 1 obrotem for wykona 3 zapytania z pętli while (albo insert albo update w zależności od warunku if)...

Moje pytanie brzmi: czy i jak można zoptymalizować tą pętle, żeby generowała jak najmniej zapytań do bazy?
Go to the top of the page
+Quote Post
nospor
post 24.06.2010, 13:39:10
Post #2





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cos kiepsko liczysz.

Na samym początku daj: $i = 0;
A nastepnie po kazdym, dosłownie po kazdym mysql_query() daj $i++;

A na koncu daj
echo $i;

Ile wyswietla? 12?


--------------------

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
poczatkujaca12
post 24.06.2010, 13:51:34
Post #3





Grupa: Zarejestrowani
Postów: 107
Pomógł: 0
Dołączył: 24.06.2010
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


hmm dziwne wyskakuje mi 10 przy 3 produktach:
efekt:
jestem w for - 1
jestem w while - 2
jestem w ifie spełniającym warunek - 3
jestem w for - 4
jestem w while - 5
jestem w ifie spełniającym warunek - 6
jestem w for - 7
jestem w while - 8
jestem w ifie spełniającym warunek - 9
jestem w for - 10

Suma: 10

nie wygląda to na straszną liczbę...
hmm nie wiem co może powodować przekraczanie limitów...
Tym bardziej że na stronie jest max 2 userków... a najczęściej 1 tongue.gif

Ten post edytował poczatkujaca12 24.06.2010, 14:51:06
Go to the top of the page
+Quote Post
erix
post 24.06.2010, 15:49:09
Post #4





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Zapytania w pętli = zuo.

  1. $z1=mysql_query("Select * from down where id_user='".$r['ius']."' and plik='".$k['plik']."'");
  2. if (mysql_num_rows($z1)!=0){
  3. mysql_query("update down set koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."' where id_user='".$r['ius']."' and plik='".$k['plik']."'");
  4. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  5. } else {
  6. mysql_query("insert into down set id_prod='".$nazwa."', id_user='".$r['ius']."', plik='".$k['plik']."', koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."'");
  7. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  8. }

Poczytaj o indeksie UNIQUE i ON DUPLICATE KEY UPDATE. Trzy zapytania zmienią się magicznie w jedno.

A jak się bardziej postarasz (posklejasz tę tablicę w odpowiednie WHERE), to podejrzewam, że całość zamknie się w jednym zapytaniu.


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
poczatkujaca12
post 24.06.2010, 21:06:13
Post #5





Grupa: Zarejestrowani
Postów: 107
Pomógł: 0
Dołączył: 24.06.2010
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


tylko akurat w tej tabelce pola id_user ani plik nie mogą być unique
chyba, że istnieje możliwość, żeby zrobić te 2 pola razem na unikalne
bo moze byc:
id_user 1 plik abc.txt
id_user 1 plik nazwa.pdf
id_user 2 plik nazwa.pdf

Ale jak już istnieje
id_user 1 plik nazwa.pdf
to drugi raz takiego rekordu dodać nie może.


Ten post edytował poczatkujaca12 24.06.2010, 21:10:17
Go to the top of the page
+Quote Post
erix
post 24.06.2010, 21:53:27
Post #6





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
tylko akurat w tej tabelce pola id_user ani plik nie mogą być unique
chyba, że istnieje możliwość, żeby zrobić te 2 pola razem na unikalne

Sprawdź, potem pogadamy. winksmiley.jpg


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
poczatkujaca12
post 24.06.2010, 22:23:23
Post #7





Grupa: Zarejestrowani
Postów: 107
Pomógł: 0
Dołączył: 24.06.2010
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Z tego co znalazłam to te UNIQUE i ON DUPLICATE KEY UPDATE tyczą się tylko jednej wybranej kolumny...
chciałam wybrać id i po tym zaktualizować, ale i tak dodało kolejny rekord.
Go to the top of the page
+Quote Post
sebekzosw
post 24.06.2010, 22:56:22
Post #8





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

Ostrzeżenie: (0%)
-----


co tak w ogóle ma robić to?
Go to the top of the page
+Quote Post
erix
post 24.06.2010, 23:11:20
Post #9





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
Z tego co znalazłam to te UNIQUE i ON DUPLICATE KEY UPDATE tyczą się tylko jednej wybranej kolumny...

Z tego, co pamiętam, to jak każdy inny indeks można nakładać.

Zawsze możesz zrobić z danych CRC32 (szybkie) i będziesz miał jedną kolumnę na indeks.


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
poczatkujaca12
post 24.06.2010, 23:47:12
Post #10





Grupa: Zarejestrowani
Postów: 107
Pomógł: 0
Dołączył: 24.06.2010
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


ok, z tym CRC podpowiedziałeś mi coś chyba podobnego i zrobiłam klucz który łączy te 2 kolumny... jej zawartość:
'id_userNazwa.pliku' i jest on unikalny
jednak nie aktualizuje mi danych...
mam zapytanie:
Kod
insert into down (id_prod, id_user, plik, crc, koniec, pobran) values ('bzdury', '1', 'bz.php', '1bz.php', koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+7,now()), '%Y-%m-%d'), pobran='20') ON DUPLICATE KEY UPDATE crc=VALUES(crc)

OK nie dodaje nowego rekordu, ale też nie aktualizuje istniejącego...

Na pytanie co to ma robić:
  1. $na = explode( '<br />', $r['npr']);
  2. // Rozbija ciąg na tablicę
  3. // wpisy tutaj wyglądają mniej więcej abc - 1<br />nazwa - 2<br />cos innego - 10<br />
  4.  
  5. $text .= "\r\n\r\nA poniżej przesyłamy linki do pobrania plików:\r\n";
  6. $kol=count($na);
  7. // zlicza ile jest takich elementów po rozdzieleniu ich po <br />
  8.  
  9. for($i=0; $i < $kol; $i++){
  10. // pętelka
  11. $nazw = explode( '<br />', $r['npr']);
  12. // jeszcze raz rozbija na tablicę, chyba zbędna operacja, ale przynajmniej nie wykorzystuje mysqla :)
  13.  
  14. $nazwa=substr($nazw[$i], 0, -4);
  15. // ucina ostatnie 4 wyrazy ze spacjami [" - 1" żeby została sama nazwa]
  16.  
  17. $zo1=mysql_query("select * from prod where nazwa='".$nazwa."'");
  18. // wybiera produkty o podanej nazwie
  19.  
  20. while($k=mysql_fetch_array($zo1)){
  21. $z1=mysql_query("Select * from down where id_user='".$r['ius']."' and plik='".$k['plik']."'");
  22. // wybiera z tabeli down to co wyżej wybrało z tabeli prod celem porównania czy dany rekord istnieje już, czy jeszcze nie.
  23.  
  24. if (mysql_num_rows($z1)!=0){
  25. // jeśli istnieje to go aktualizuje
  26.  
  27. mysql_query("update down set koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."' where id_user='".$r['ius']."' and plik='".$k['plik']."'");
  28. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  29. } else {
  30. // w przeciwnym wypadku tworzy nowy wpis.
  31.  
  32. mysql_query("insert into down set id_prod='".$nazwa."', id_user='".$r['ius']."', plik='".$k['plik']."', koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."'");
  33. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  34. }
  35. }
  36. }


Generalnie jest to do pobierania i generowania unikalnych linków do określonego pliku.
Dany użytkownik może ściągnąć plik max X razy, i link jest aktywny X dni.

hmm pytanie czy zapytanie z ON DUPLICATE KEY UPDATE rzeczywiście coś optymalizuje...
Bo w moim przypadku w pętli while wykonuja sie 2 zapytania...
jedno wybierające a drugie od warunku dodające lub aktualizujące...
a znalazłam, że ON DUPLICATE KEY UPDATE generuje 2 zapytania do bazy - pierwsze dodające i drugie [jeżeli wpis istniał] aktualizujące [tak zrozumiałam]... więc pozbywam się selecta i warunków [2 zapytań]... zamieniam na jedno zapytanie, generujące 2 zapytania do bazy z ON DUPLICATE KEY UPDATE??

=> http://forum.php.pl/index.php?showtopic=94...rt=#entry566638

Ten post edytował poczatkujaca12 25.06.2010, 00:48:38
Go to the top of the page
+Quote Post
sebekzosw
post 25.06.2010, 09:11:21
Post #11





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

Ostrzeżenie: (0%)
-----


a nie lepiej to będzie sprawdzać przed wygenerowaniem linka ? tzn koleś wchodzi na podstronę gdzie jest ten link i na początku zostaje sprawdzany. wtedy liczba zapytań znacząco się zmniejszy bo nie każdy link będzie aktualizowany (tylko wtedy jak ktoś wejdzie)


czyli ostatecznie wyglądałoby to tak:


  1. $z1 = mysql_fetch_assoc(mysql_query("Select * from down where id_user='".$r['ius']."' and plik='".$k['plik']."'"));
  2.  
  3. if (!empty($z1))
  4. {
  5. mysql_query("update down set koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."' where id_user='".$r['ius']."' and plik='".$k['plik']."'");
  6. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  7. }
  8. else
  9. {
  10. mysql_query("insert into down set id_prod='".$nazwa."', id_user='".$r['ius']."', plik='".$k['plik']."', koniec=DATE_FORMAT(TIMESTAMPADD(DAY,+".$ldni.",now()), '%Y-%m-%d'), pobran='".$lpobran."'");
  11. $text .= "\r\n ".$adres."/pobierz/".$r['ius']."/".$k['plik']."\r\n";
  12. }


oczywiście trzeba dostosować to do podstrony


mam nadzieje, że rozumiesz mój przekaz smile.gif

Ten post edytował sebekzosw 25.06.2010, 09:15:54
Go to the top of the page
+Quote Post
erix
post 25.06.2010, 09:28:41
Post #12





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
a znalazłam, że ON DUPLICATE KEY UPDATE generuje 2 zapytania do bazy - pierwsze dodające i drugie [jeżeli wpis istniał] aktualizujące [tak zrozumiałam]... więc pozbywam się selecta i warunków [2 zapytań]... zamieniam na jedno zapytanie, generujące 2 zapytania do bazy z ON DUPLICATE KEY UPDATE??

Nie pamiętam szczegółów, ale nawet jeśli, to te dwa zapytania są już realizowane bezpośrednio przez DBMS, czyli z pominięciem wyciągania jakichkolwiek danych do front-endu (czyli do PHP).

A jak nazwa wskazuje, UNIQUE jest indeksem, czyli sprawdzenie danej wartości jest ułamkiem sekundy. Generalnie lepiej jest obarczać takimi zadaniami bazę danych, oczywiście w granicach rozsądku, ale IMHO Twoja sytuacja jest tą właściwą. winksmiley.jpg


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
poczatkujaca12
post 25.06.2010, 21:43:42
Post #13





Grupa: Zarejestrowani
Postów: 107
Pomógł: 0
Dołączył: 24.06.2010
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Znalazłam biggrin.gif
Okazało się, że problem nie leżał w pętli... tzn nie tej smile.gif

W kolejnym etapie miałam błąd w pliku odpowiadający za ściąganie pliku przez usera...
udało się naprawić [pierdółka - takie błędy są najgorsze], po czym okazało się, że w ogóle to jest nie potrzebne
[bo zupełnie zrezygnowałam z tego rozwiązania tongue.gif ]

I dzięki za pomoc smile.gif

Ten post edytował poczatkujaca12 25.06.2010, 21:44:31
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 14.08.2025 - 12:45