Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Pierwsze zapytanie trwa 3 sekundy a później 0,001 :(
TomASS
post
Post #1





Grupa: Zarejestrowani
Postów: 1 660
Pomógł: 13
Dołączył: 9.06.2004
Skąd: Wrocław i okolice

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


Cześc - mam takie zapytanie:
  1.  
  2. SELECT
  3.  
  4. AVG( IF(DR.rodzaj ='CCC',
  5. ((DRP.cena1)-(DRP.rabat1+DRP.rabat2+DRP.rabat3+DRP.rabat4+DRP.rabat5)),
  6. IF(DR.rodzaj ='WWW',
  7. IF((P.flaga1 = '1' OR P.oznaczenie LIKE '%BBB%' OR P.oznaczenie LIKE '%BBB%' OR P.oznaczenie LIKE '%BBB%'),
  8. (DRP.cena1-(DRP.rabat1+DRP.rabat2)-DRP.rabat3-DRP.rabat4),
  9. (DRP.cena1-(DRP.rabat1+DRP.rabat2)-DRP.rabat3-DRP.rabat4+DRP.rabat5)),
  10. IF(P.flaga2 = '1' OR P.oznaczenie LIKE '%BBB%' OR P.oznaczenie LIKE '%BBB%' OR P.oznaczenie LIKE '%BBB%',
  11. (DRP.cena1-(DRP.rabat1+DRP.rabat2)-DRP.rabat3-DRP.rabat4-DRP.rabat5),
  12. (DRP.cena1-(DRP.rabat1+DRP.rabat2)-DRP.rabat3+DRP.rabat4-DRP.rabat5-DRP.rabat6))) )) AS Srednia
  13.  
  14. FROM
  15. cennik_pozycje AS DRP LEFT JOIN
  16. cennik AS DR ON DR.id = DRP.id_cennik LEFT JOIN
  17. miejsca_dostaw AS MD ON DRP.id_miejsce = MD.id LEFT JOIN
  18. produkty AS P ON P.id = DRP.id_produkt
  19. WHERE
  20. MD.id_klient = 5000002 AND
  21. P.id IN (100000001,100000002) AND
  22. DR.STATUS = 'aktualny' AND
  23. DR.miejsce = 'akt' AND
  24. DRP.miejsce = 'akt' AND
  25. DR.rodzaj IN('CCC','WWW','LLL');


Nic wielce podniecającego - liczenie średniej. Średnia liczy się w zależności od pola DR.rodzaj wg różnych pól (czasmi się odejmuje rabaty, czasasmi nie - w zależnosci od DR.rodzaj).
Złączeń jest kilka - od cennika, po pozycje w cenniku, w zależności od klienta oraz produktu.
Wykonuje te zapytanie około 100 razy gdzie zmienia się pole id_klient oraz P.id
  1. MD.id_klient = 5000002 AND
  2. P.id IN (100000001,100000002) AND

Problem w tym, że za pierwsyzm razem te zapytanie (z takimi parametrami jak wyżej) wykonuje się 3,5 sekundy (co przy 100 daje czas około 5-6min), a po ponownym uruchomieniu (np. po minucie) - z tymi samimi parametrami - już tylko 0,001s (IMG:style_emoticons/default/sad.gif)

Nie wiem co zoptymalizować - indeksy są, nie jest to coś skomplikowanego. Może te IFy w AVG? Tylko jak je obejść?
Go to the top of the page
+Quote Post
mmmmmmm
post
Post #2





Grupa: Zarejestrowani
Postów: 1 421
Pomógł: 310
Dołączył: 18.04.2012

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


Po pierwsze spróbuj się pozbyć LEFT JOINów - wydaje mi się, że nic nie zmienią.
Po drugie sprawdź z jakich indeksów MOŻESZ skorzystać i te pola daj do WHERE. Resztę staraj się filtrować w samej formule. Albo dorób indeksy. Oczywiście sprawdź EXPLAINem.
Aha, a różnice w czasach wynikają z tego, że za drugim razem bierze z CACHE,.

Ten post edytował mmmmmmm 24.09.2014, 11:45:52
Go to the top of the page
+Quote Post
TomASS
post
Post #3





Grupa: Zarejestrowani
Postów: 1 660
Pomógł: 13
Dołączył: 9.06.2004
Skąd: Wrocław i okolice

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


Cześć,
Cytat
Po pierwsze spróbuj się pozbyć LEFT JOINów - wydaje mi się, że nic nie zmienią.

Zmieniają - musze mieć takie dane w WHERE:
  1. MD.id_klient = 5000002 AND
  2. P.id IN (100000001,100000002) AND
  3. DR.STATUS = 'aktualny' AND
  4. DR.miejsce = 'akt' AND
  5. DRP.miejsce = 'akt' AND
  6. DR.rodzaj IN('CCC','WWW','LLL');


niestety nie mogę się ich pozbyć

Cytat
Po drugie sprawdź z jakich indeksów MOŻESZ skorzystać i te pola daj do WHERE.

Mam indeksy i dokładnie z tych co korzystam w WHERE. Tabela DRP ma 2mln rekordów, inne po kilknaście tysięcy. Gdyby nie indkesy nie trwałoby to 3s (IMG:style_emoticons/default/sad.gif)

Cytat
Oczywiście sprawdź EXPLAINem.

Zrobiłem - wskazało tylko, że poprawnie używam indeksów

Cytat
Aha, a różnice w czasach wynikają z tego, że za drugim razem bierze z CACHE,.

Używając SELECT MYSQL_NO_CASHE identyczna sytuacja - za pierwszym razem 3sekundy, za kolejnymi 0,001
Go to the top of the page
+Quote Post
mmmmmmm
post
Post #4





Grupa: Zarejestrowani
Postów: 1 421
Pomógł: 310
Dołączył: 18.04.2012

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


Pisząc, żebyś pozbył się LEFT JOINów miałem na m,yśli zastąpienie je JOINami.
Go to the top of the page
+Quote Post
sowiq
post
Post #5





Grupa: Zarejestrowani
Postów: 1 890
Pomógł: 339
Dołączył: 14.12.2006
Skąd: Warszawa

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


Zrób dwie rzeczy. Po pierwsze zobacz jak długo wykonuje się zapytanie:
  1. SELECT *
  2. FROM cennik_pozycje AS DRP
  3. LEFT JOIN [...]
  4. WHERE
  5. MD.id_klient = 5000002 AND
  6. P.id IN (100000001,100000002) AND
  7. DR.STATUS = 'aktualny' AND
  8. DR.miejsce = 'akt' AND
  9. DRP.miejsce = 'akt' AND
  10. DR.rodzaj IN('CCC','WWW','LLL');


Po drugie zobacz co zwróci:

  1. EXPLAIN
  2. SELECT *
  3. FROM cennik_pozycje AS DRP
  4. LEFT JOIN [...]
  5. WHERE
  6. MD.id_klient = 5000002 AND
  7. P.id IN (100000001,100000002) AND
  8. DR.STATUS = 'aktualny' AND
  9. DR.miejsce = 'akt' AND
  10. DRP.miejsce = 'akt' AND
  11. DR.rodzaj IN('CCC','WWW','LLL');


Explain pokaże Ci brakujące indeksy i inne problemy z Twoim zapytaniem.

A co do tego, że drugie wykonanie zapytania trwa znacznie dłużej krócej - jest to całkowicie naturalne. MySQL ma swój wewnętrzny cache, który pozwala znacznie przyspieszyć kolejne wykonanie tego samego zapytania.

Ten post edytował sowiq 24.09.2014, 15:21:15
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 18.09.2025 - 09:04