Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Nie zbyt skomplikowane zapytanie (z LEFT JOIN) wykonuje się zbyt długo (nawet ponad 2 sekundy)
Forum PHP.pl > Forum > Bazy danych > MySQL
Sajrox
Witam,

Otóż tworze porównywarkę cen gdzie której chce połączyć 2 tabele i wyciągnąć z niej dane.
Same zapytanie nie jest jakoś skomplikowane ale mimo tego wykonuje się strasznie długo przy dużej ilości rekordów w bazie.
Próbowałem już wielu rzeczy, zmiana struktury bazy itp. i nic. Zawsze przy wielu rekordach w bazie zapytanie strasznie długo się wykonuje. Dodam że także zastosowałem indexy.


Mam 2 tabele "product" oraz "product_offer" (tabele InnoDB)

tabela "product"
id | name | date_added | main
Indexy na: id, name, main

pole main informuje nas czy produkt jest produktem czy ofertą, gdy dany rekord w polu main ma 0 to znaczy że jest przypisany do innego produktu z tej samej tabeli. Przypisania zawarłem w tabeli "product_offer"
id_product | id_offer | price
Indexy na: id_product, id_offer oraz UNIQUE na id_product i id_offer w jednym


Chce wyciąganć wszystkie produktu z nazwa, liczbą ofert do nich przypisaną oraz minimalną cenę.
Oto zapytanie które to wykonuje jednak czas wykonania wynosi ponad 2 s :/

  1. SELECT p.id,p.name,count(po.id_offer) AS offers,min(po.price) AS price_min FROM pco_product AS p LEFT JOIN pco_product_offer AS po ON p.id = po.id_product WHERE (p.main = '1') GROUP BY po.id_product ORDER BY p.name ASC LIMIT 0, 20


Co wy o tym myslicie ? Jak można to przyśpieszyć ?


Dodam także że inne zapytania na innych tabelach ze złączeniami LEFT JOIN także wykonuje się długo przy takiej liczbie rekordów w bazie sad.gif
artega
Cytat
pole main informuje nas czy produkt jest produktem czy ofertą, gdy dany rekord w polu main ma 0 to znaczy że jest przypisany do innego produktu z tej samej tabeli.

To jedna z przyczyn - indeksy na polach które mają za zadanie przechowywać informacje typu 0 lub 1 są bardzo słabe. Rozbij dane na dwie tabele lub zainteresuj się partycjonaowaniem. Kolejnym słabym punktem jest użycie w jednym i tym samym zapytaniu COUNT i MIN. W twoim przypadku jeżeli założyć, że w bazie jest 1 mln rekordów z czego połowa w kolumnie main posiada wartość 1 to baza skanuje 500 000 tyś. rekordów, więć trudno oczekiwać lepszej wydajności. Użyj EXPLAIN po więcej szczegółów.
Sajrox
A może jakiś przykład z tym partycjonowaniem ? Niestety nie miałem z tym jeszcze do czynienia, Czytam z linka którego podałeś ale jakoś nie bardzo udaje mi się coś z tym zrobić sad.gif
Którą tabele mam dokładnie rozbić na 2 części ? I w czym to może pomóc ?


Mam jeszcze jeden problem z z bazą MyISam a InnoDB. Otóż posiadam pewne proste zapytanie. W tabeli typu InnoDB wycaga 0 wyników a gdy zamienię tą tabelę na MyIsam to prawidłowo wyciąga wyniki. Dziwne troche :/
artega
Cytat
A może jakiś przykład z tym partycjonowaniem ? Niestety nie miałem z tym jeszcze do czynienia, Czytam z linka którego podałeś ale jakoś nie bardzo udaje mi się coś z tym zrobić

Szukanie nie boli smile.gif Tutaj znajdziesz co trzeba.
Cytat
Którą tabele mam dokładnie rozbić na 2 części ? I w czym to może pomóc ?

Na to pytanie odpowiesz sobie sam kiedy przeczytasz atykuł.
Cytat
Mam jeszcze jeden problem z z bazą MyISam a InnoDB. Otóż posiadam pewne proste zapytanie. W tabeli typu InnoDB wycaga 0 wyników a gdy zamienię tą tabelę na MyIsam to prawidłowo wyciąga wyniki. Dziwne troche :/

Jasnowidzem niestety nie jestem, więc jeżeli nie podasz konkretnego przykładu, przykładowych danych i oczekiwanego wyniku to nic nie doradze.
Sajrox
Ok dzieki poszukam i dam znać czy się udało smile.gif
A z tą widocznością wyników to restart Apacha wyeliminował ten problem smile.gif


edit:
Kurcze kiepsko z moim angielskim :/
A może jakiś przykład od siebie jeśli to nie kłopot.

Chce założyć partycję np. na pole "date_added". Może malutki przykłądzik ? Będe bardzo wdzieczny smile.gif
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.