Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Problem z b.długim zapytaniem
m72
post 5.06.2014, 23:23:41
Post #1





Grupa: Zarejestrowani
Postów: 86
Pomógł: 0
Dołączył: 25.12.2012

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


Witam, pomóżcie ułożyć prawidłowo zapytanie bo nie dźwigam tematu.
Są 4 tabele:
-firmy
-produkty
-produkt_firma
-miasta.
produk_firma to tabela łącząca firmy z produktami






Pisząc po ludzku chodzi o to.
Wyświetl firmy (łącznie z miastami w których one są) które oferują produkt o id_produktu=577 i znajdują się w odległości mniejszej niż 20km od miasta o współrzędnych 21.20563 i 50.56122 i dodatkowo status firmy=1 i jakieś tam sortowanie na koniec.

W kwestii wytłumaczenia.
Mój plan był taki żeby pierwsze obliczyć w php i odciąć wszystkie niepotrzebne miejscowości poza tymi które znajdują się w zakresie poszukiwań (powstaje kwadrat z miastami).
Następnie trzeba "zakreślić w tym kwadracie koło i odciąć niepotrzbne rogi" czyli wzór na koło x^2+y^2<r^2 a w mysql - (sqrt( POW(dlugosc-21.20563,2)+POW(szerokosc-50.56122,2) )<20*0.013994 )
Współczynnik 0.013994 musi być ale to nie ważne teraz. Miast w bazie jest 1000 a docelowo kiedyś 50000 więc nie chce mysleć co się wtedy będzie działo smile.gif


Ostatecznie wszystko działa ale cholernie woooolno bo takie zapytanie wykonuje się około 0.5s a każda część z osobna, nawet
ta obliczająca pierwisatki - 0.001s, różnica kolosalna. Dopiero zaczynam zabawe w sql i nie bardzo kumam jak to zoptymalizować.
Pomóżcie, oto zapytanie.

  1. SELECT firmy.nazwa_firmy, miasta.miasto FROM firmy
  2. JOIN miasta ON firmy.id_miasta = miasta.id_miasta WHERE
  3. id_firmy IN
  4. (SELECT id_firmy FROM produkt_firma WHERE id_produktu='577')
  5. AND miasta.id_miasta IN
  6. (
  7. SELECT id_miasta FROM miasta WHERE dlugosc >=21.8 AND dlugosc <=22.6 AND szerokosc >= 49.42 AND szerokosc <= 51.04 AND (sqrt( POW(dlugosc-21.20563,2)+POW(szerokosc-50.56122,2) )<20*0.013994 )
  8. )
  9. AND status_firmy='1' ORDER BY rodzaj_konta_nr DESC, data_aktywacji ASC LIMIT 0, 100
  10.  
  11.  


ps. pewne rzeczy pominąłem i uprościłem a współrzędne geo są z rękawa bo nie mam na razie prawdziwych
ps ps. zdaje sobie sprawę że w zapytaniu jest zapewne wiele bezsensów
Go to the top of the page
+Quote Post
Pyton_000
post 6.06.2014, 07:06:03
Post #2





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


a coś takiego? pisane z placa
  1. SELECT
  2. pf.id_produktu, m.miasto, f.nazwa_firmy
  3. FROM
  4. produkt_firma pf
  5. JOIN firmy f ON (f.id = pf.id_firmy)
  6. JOIN miasta m ON (m.id = f.id_miasta)
  7. WHERE
  8. pf.produkt_id = 111 AND
  9. f.status_firmy = '1' AND
  10.  
  11. m.dlugosc >=21.8 AND
  12. m.dlugosc <=22.6 AND
  13. m.szerokosc >= 49.42 AND
  14. m.szerokosc <= 51.04 AND
  15. (sqrt( POW(dlugosc-21.20563,2)+POW(szerokosc-50.56122,2) )<20*0.013994 );
Go to the top of the page
+Quote Post
m72
post 6.06.2014, 14:28:30
Post #3





Grupa: Zarejestrowani
Postów: 86
Pomógł: 0
Dołączył: 25.12.2012

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


Dzięki, działa to w takiej formie.

  1. SELECT
  2. produkt_firma.id_produktu, miasta.miasto, miasta.dlugosc, miasta.szerokosc, firmy.nazwa_firmy
  3. FROM
  4. produkt_firma
  5. JOIN firmy ON (firmy.id_firmy = produkt_firma.id_firmy)
  6. JOIN miasta ON (miasta.id_miasta = firmy.id_miasta)
  7. WHERE
  8. produkt_firma.id_produktu = 577 AND
  9. firmy.status_firmy = '1'
  10.  
  11. AND
  12.  
  13. miasta.dlugosc >=21.8 AND
  14. miasta.dlugosc <=22.6 AND
  15. miasta.szerokosc >= 49.42 AND
  16. miasta.szerokosc <= 51.04 AND
  17. (sqrt( POW(dlugosc-21.20563,2)+POW(szerokosc-50.56122,2) )<250*0.013994 );


Teraz zapytanie się wykonuje szybciej, około 0.14s dobre i to smile.gif W bazie jest dosłownie kilkanaście wpisów a miast tylko 1000. Strach pomysleć co to bedzie gdy miast i wsi będzie ok 50000 smile.gif
Go to the top of the page
+Quote Post
Pyton_000
post 6.06.2014, 14:42:15
Post #4





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


może masz nie pozakładane indeksy na odpowiednie kolumny bo na to by wskazywało
Go to the top of the page
+Quote Post
Damonsson
post 6.06.2014, 21:34:35
Post #5





Grupa: Zarejestrowani
Postów: 2 355
Pomógł: 533
Dołączył: 15.01.2010
Skąd: Bydgoszcz

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


A bez
  1. AND
  2.  
  3. miasta.dlugosc >=21.8 AND
  4. miasta.dlugosc <=22.6 AND
  5. miasta.szerokosc >= 49.42 AND
  6. miasta.szerokosc <= 51.04 AND
  7. (sqrt( POW(dlugosc-21.20563,2)+POW(szerokosc-50.56122,2) )<250*0.013994 );



ile czasu?
Go to the top of the page
+Quote Post
m72
post 7.06.2014, 16:52:49
Post #6





Grupa: Zarejestrowani
Postów: 86
Pomógł: 0
Dołączył: 25.12.2012

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


No trochę krócej ale ciężko mi ocenić bo te czasy są raz 0,14 raz 0,5 a czasem 0,00 (bezpośrednio na serwerze przez putty)
a ta wersja skrócona cały czas 0,00
Go to the top of the page
+Quote Post
Damonsson
post 7.06.2014, 20:19:31
Post #7





Grupa: Zarejestrowani
Postów: 2 355
Pomógł: 533
Dołączył: 15.01.2010
Skąd: Bydgoszcz

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


Musisz po prostu znaleźć, co Ci robi ten długi czas. Podziel sobie zapytanie, usuwaj konkretne where i wtedy zlokalizujesz przyczynę. Sprawdzaj zapytania z wyłączonym cache (znajdzie w google jak to zrobić).
Go to the top of the page
+Quote Post
Pyton_000
post 8.06.2014, 14:33:18
Post #8





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Ew. zrób explain i pokaż wynik z całego zapytania
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: 16.07.2025 - 07:21