Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Pomoc w optymalizacji
Wasper
post 22.05.2012, 11:10:52
Post #1





Grupa: Zarejestrowani
Postów: 82
Pomógł: 1
Dołączył: 18.09.2011

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


Czesc,
mam zapytanie, ktore jeszcze nie zawiera 100% okreslonych pozycji, a juz generuje sie ponad 4s.
Baza jest w miare przyzwoicie zindeksowana. Chcialbym zasiegnac Waszej opinii, czy jest mozliwosc ulepszenia samego zapytania.

Zapytanie:
  1. SELECT
  2. tfirm.name fname,
  3. tfirm.city fcity,
  4. tfirm_navo.navo_code ncode,
  5. tperson.name pname,
  6. tperson.family pfamily,
  7. psr.name psrname,
  8. psr.family psrfamily,
  9. um_str.user_id um,
  10. tperson.detail_process,
  11. tperson.mail_info,
  12. tperson.own_business,
  13. telefon.telefon ismobile,
  14. mail.mail ismail,
  15. logowania.suma log_sum,
  16. logowania.last_log ostatni_log,
  17. zamowienia.liczba zam_value
  18. FROM
  19. tperson
  20. INNER JOIN tuser_firm ON tuser_firm.user_id = tperson.user_id
  21. INNER JOIN tfirm ON tfirm.id = tuser_firm.firm_id
  22. INNER JOIN tfirm_navo ON tfirm_navo.firm_id = tfirm.id
  23. INNER JOIN (
  24. SELECT count( tuser_log.id ) suma, IF(max(tuser_log.timestamp) IS NULL, '0000-00-00 00:00:00', max(tuser_log.timestamp)) last_log, tperson.user_id
  25. FROM tperson
  26. LEFT JOIN tuser_log ON tperson.user_id = tuser_log.user_id
  27. AND log_type =1 WHERE tperson.role=7
  28. GROUP BY tperson.user_id
  29. )logowania ON logowania.user_id = tperson.user_id
  30. INNER JOIN tfirm_psr ON tfirm_psr.firm_code=tfirm_navo.navo_code
  31. INNER JOIN tteren_user ON tteren_user.teren_id=tfirm_psr.psr_field
  32. INNER JOIN tuser_navo ON tuser_navo.navo_id=tteren_user.navo_user_id
  33. INNER JOIN tperson psr ON psr.user_id=tuser_navo.user_id
  34. INNER JOIN tstructure um_str ON um_str.child=tuser_navo.navo_id
  35. INNER JOIN
  36. (SELECT tperson.user_id uid, IF((tperson_mobile.mobile='' OR tperson_mobile.mobile IS NULL), 0, 1) telefon
  37. FROM tperson LEFT JOIN tperson_mobile ON tperson.user_id=tperson_mobile.user_id WHERE tperson.role=7) telefon ON telefon.uid=tperson.user_id
  38. INNER JOIN
  39. (SELECT tperson.user_id uid, IF((tperson_mail.mail='' OR tperson_mail.mail IS NULL), 0, 1) mail
  40. FROM tperson LEFT JOIN tperson_mail ON tperson.user_id=tperson_mail.user_id WHERE tperson.role=7) mail ON mail.uid=tperson.user_id
  41. INNER JOIN
  42. (SELECT tperson.user_id uid, count(torder.id) liczba FROM tperson LEFT JOIN torder ON tperson.user_id=torder.user_id GROUP BY tperson.user_id) zamowienia ON zamowienia.uid=tperson.user_id
  43. WHERE
  44. tperson.role=7 AND tfirm.STATUS=1


probowalem pozbyc sie podzapytan i stworzylem cos takiego

  1. SELECT
  2. tfirm.name fname,
  3. tfirm.city fcity,
  4. tfirm_navo.navo_code ncode,
  5. tperson.name pname,
  6. tperson.family pfamily,
  7. psr.name psrname,
  8. psr.family psrfamily,
  9. um_str.user_id um,
  10. tperson.detail_process,
  11. tperson.mail_info,
  12. tperson.own_business,
  13.  
  14. count( tuser_log.id ),
  15. IF(max(tuser_log.timestamp) IS NULL, '0000-00-00 00:00:00', max(tuser_log.timestamp)),
  16. IF((tperson_mobile.mobile='' OR tperson_mobile.mobile IS NULL), 0, 1),
  17. IF((tperson_mail.mail='' OR tperson_mail.mail IS NULL), 0, 1),
  18. count(torder.id)
  19.  
  20. FROM
  21. tperson
  22. INNER JOIN tuser_firm ON tuser_firm.user_id = tperson.user_id
  23. INNER JOIN tfirm ON tfirm.id = tuser_firm.firm_id
  24. INNER JOIN tfirm_navo ON tfirm_navo.firm_id = tfirm.id
  25. LEFT JOIN tuser_log ON tuser_log.user_id=tperson.user_id AND tuser_log.log_type=1
  26. LEFT JOIN tperson_mobile ON tperson_mobile.user_id=tperson.user_id AND tperson_mobile.STATUS=1
  27. LEFT JOIN tperson_mail ON tperson_mail.user_id=tperson.user_id AND tperson_mail.STATUS=1
  28. LEFT JOIN torder ON torder.user_id=tperson.user_id
  29.  
  30. INNER JOIN tfirm_psr ON tfirm_psr.firm_code=tfirm_navo.navo_code
  31. INNER JOIN tteren_user ON tteren_user.teren_id=tfirm_psr.psr_field
  32. INNER JOIN tuser_navo ON tuser_navo.navo_id=tteren_user.navo_user_id
  33. INNER JOIN tperson psr ON psr.user_id=tuser_navo.user_id
  34. INNER JOIN tstructure um_str ON um_str.child=tuser_navo.navo_id
  35.  
  36. WHERE
  37. tperson.role=7 AND tfirm.STATUS=1 AND
  38. HAVING count( tuser_log.id )=0
  39. GROUP BY tperson.user_id, tuser_log.user_id, torder.user_id


dziala o wiele szybciej
ale pojawia sie kwestia filtrowania wg countow , gdyz wrzucajac do warunku where przykladowo count( tuser_log.id )=1 wyrzuca "invalid use of group function".
Moze to jakas moja niewiedza... dlatego chcialbym zasiegnac Waszej opinii.
A gory dzieki za pomoc.

edit.
zapomnialem dodac, ze ify sa wstawione po to, zeby uniknac wartosci NULL w zapytaniu (kwestia uzycia kwerendy w frameworku.. nie ma filtrow obslugujacych nulle)

Wasp

update. zapomnialem o having smile.gif moze to z racji nieprzespanej nocy wink.gif

Ten post edytował Wasper 22.05.2012, 09:19:57
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
alegorn
post 22.05.2012, 11:15:49
Post #2





Grupa: Zarejestrowani
Postów: 341
Pomógł: 40
Dołączył: 23.06.2009

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


uff, ale to wielkie.
nie mam czasu analizowac calosci, ale odniose sie do tego kawalka:


  1. IF(max(tuser_log.timestamp) IS NULL, '0000-00-00 00:00:00', max(tuser_log.timestamp)),
  2. IF((tperson_mobile.mobile='' OR tperson_mobile.mobile IS NULL), 0, 1),
  3. IF((tperson_mail.mail='' OR tperson_mail.mail IS NULL), 0, 1),



przedefiniuj te kolumny na NOT NULL, i ustaw wartosc domyslna.
ominiesz w ten sposob kilka operacji czyli czysty zysk. [zwlaszcza na OR]

ogolnie stosowanie wartosci NULL w bazie danych oznacza ze najprawdopodobniej projekt jest nieprzemyslany / baza nie jest znormalizowana

przemysl, czy optymalizacja tylko zapytania da ci efekt.
pokaz jakiegos explaina, to tez troche nam podpowie.

co do indeksow, radze uwazac.
ja np wczoraj wywalilem wczoraj primary, na zastepczym indeksie (czyli popularny autoinc).
po jego wywaleniu, i zalozeniu zwyklego indeksu na inna kolumne - zapytanie z czasu ~~4sec spadlo do 0,8
po kolejnej rozkminie i przebudowie tabeli - uzyskalem efekt na poziomie ~~0,02

z ~~4 sec na ~~0,02 wiec optymalizacja zapytania o conajmniej 200%

pisze to dlatego - ze chce zwrocic uwage, iz nie uzyskalbym az takiej redukcji czasu zmieniajac tylko kwerende.
(oczywiscie najwazniejszym kryterium tabeli byl odczyt.)
Go to the top of the page
+Quote Post

Posty w temacie


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 - 20:23