[MySQL]Optymalizacja: SELECT z 4 tabel

0

Witam. Mam dwie wersje zapytań z 3 i 4 tabel. W zapytaniu z trzech tabel wszystkie połączone są kolumną products_id i wszystko działa OK :

SELECT p.products_model , pd.products_name , p.products_quantity , p.products_price, p.products_status, p2c.categories_id
FROM products_description pd, products p, products_to_categories p2c
WHERE pd.products_id = p.products_id AND p.products_id = p2c.products_id
ORDER BY products_name;

Po dodaniu czwartej tabeli : categories_description zawierającej categories_id i categories_name (brak products_id) która zamiast numeru kategorii (p2c.categories_id) wyświetla nazwę kategorii (cd.categories_name) czas wykonania zapytania zwiększył się ok.10-krotnie(15sek na localhost). Moje zapytanie z 4 tabel wygląda tak:

SELECT p.products_model , pd.products_name , p.products_quantity , p.products_price, p.products_status, cd.categories_name
FROM products_description pd, products p, products_to_categories p2c, categories_description cd
WHERE pd.products_id = p.products_id AND p.products_id = p2c.products_id AND p2c.categories_id = cd.categories_id
ORDER BY products_name;

Tabela products_to_categories zawiera: products_id i categories_id.
W jaki sposób prawidłowo konstruować powyższy typ zapytań jeśli wszystkie tabele nie są połączone wspólnym polem aby nie produkować iloczynów kartezjańskich (LEFT JOIN , podzapytania)? Przeszukałem różne przykłady,kursy,porady ale nic zbliżonego do mojego nie znalazłem. Chciałbym jeszcze sporo zmienić w tym zapytaniu (np.stawka VAT = następna tabela , products_status zamiast 0 i 1 = aktywny i nieaktywny itp.) a nie mam zamiaru zawracać głowy z każdym małym problemikiem.

Używam MySQL5, Delphi DBGrid , a struktura bazy typowa z e-shopu, indeksy na w/w polach tabel są.

Dziękuję za wszelkie porady.
R.J.

0

Yyyy, o ile mnie sie wydaje to Twoje rozwiazanie to wlasnie iloczyn kartezjanski, dlatego pewnie tak drastycznie spada wydajnosc. Uzyj joina (bo do tego zostal wymyslony) powinno byc znacznie szybsze.

Ile masz rekordow w poszczegolnych tabelach, ze trwa to az 15s?

0

johny mądry optymalizator i tak zamieni to na join.

Inna sprawa czy masz indeksy na polach z id w nazwie i co pokazuje explain

no i zacznij od lektury http://dev.mysql.com/doc/refman/5.0/en/query-speed.html

0

Jeszcze pytanie czy pola po których się łączysz są identycznych typów. Przy niektórych SZDB join po polach Decimal(13, 1) i Decimal(12) owocuje indeksowaniem.

0

Dołóż indeksy na kluczach obcych - MySQLu bardzo pomagają, bo ten system nie zna żadnych efektywnych algorytmów złączeń prócz INDEX NESTED LOOPS JOIN. Wiec jak nie masz indeksu, to jest wlaśnie taka masakra.

Sprawdź też jeszcze to zapytanie EXPLAINem. Zobacz, czy kolejność złaczeń jest dobra. Miałem kilka razy sytuację, że optimizer MySQL głupiał już przy 3 tabelach i stosował złą kolejność złączeń. W ostateczności w MySQL masz opcję ręcznego wymuszenia kolejności złaczeń przez STRAIGHT JOIN, ale naprawdę stosuj to w ostateczności. Nie powinno mieć za to znaczenia, czy warunek podajesz jako JOIN czy w sekcji WHERE, MySQL automatycznie go przeniesie i nie będzie robił iloczynów kartezjańskich.

0

Witam i dzięki za podpowiedzi.Wieczorem usiądę nad tematem i przestudiuję w/w wskazówki.
Na pewno nie mam foreign keys bo tabele są MyISAM.
Pozdrawiam R.J.
Ps. Produktów w bazie jest 9202 , kategorii 138.

0

Sukces.
Zmieniłem tabelki na InnoDB bez jakichkolwiek innych zmian i mam dla w/w 4 tabel:
"9202 rows fetched in 0.2407s (0.0121s)".
Muszę trochę poczytać o InnoDB bo nie wiem z jakiego powodu nastąpiła ta poprawa.
Sorry za naciąganie , ale może ktoś pokazał by mi poprawną wersje mojego SELECT'a z użyciem JOIN (-ów) bo moje nocne zmagania nie zadziałały.
Jeszcze raz dzięki za rady.

1 użytkowników online, w tym zalogowanych: 0, gości: 1