[MySQL] LEFT JOIN - strasznie wolny
Yarro - 01-08-2006 01:51
[MySQL] LEFT JOIN - strasznie wolny
Witam,
W wielkim uproszczeniu struktura danych jest nastepujaca (2 tabele):
transport ========= nr_transportu int (primary key, not null) opis_transportu varchar(30) data_wyjazdu datetime nr_zamowienia varchar(10) (null mozliwy)
zamowienia ========== nr_zamowienia varchar(10) (primary key, not null) opis_zamowienia varchar(30) nr_transportu int
-------------------------------------------------- w bazie MySQL 4.1.19 (win) jest: zamowienia: 1400 rekordow transporty: 800 rekordow
Dopiero jak znany jest nr_transportu dla konkretnego zamowienia updotowana jest tabela zamowienia gdzie w pole nr_transportu wpisujemy numer transportu. Sa wiec zamowienia, ktrore w polu nr_transportu maja NULL.
Chce wybrac wszystkie nr transportu (ktore wyjechaly) wraz z infor z tabeli zamowienia ale konicznie musza sie na liscie pojawic rowniez transporty, ktore nie maja przypisanych numerow transportu w polu nr_transportu:
select tra.nr_transportu, zam.nr_zamowienia from (transporty tra LEFT JOIN zamowienia zam on tra.nr_transportu=zam.nr_transportu) WHERE tra.data_wyjazdu is not null order by tra.nr_transportu desc;
w rezultacie otrzymuje okolo 290 rekordow ale przetwarzanie tego zapytania trwa okolo 6-7 sekund.
Te dwie tabelki wrzucilem do MS ACCESS. Z reki wpisalem dokladnie to samo zamowienia i na tym samym kompie czas wykonywania jest bardzo krotki: rezultaty pojawiaja sie natychmiast po odpaleniu kwerendy !!!
Dlaczego LEFT JOIN jest w MySQL taki wolny (jak na chwile zamienilem go na INNER JOIN zapytanie wykonalo sie w Mysqlu w 0,01 sec). Skoro Access poradzil sobie z tym zapytaniem w ułamek sekundy to co zrobic aby tak samo szybko działało ono w MYSQL.
Pozdrawiam Yarro
Artur Gancarz - 02-08-2006 00:06
Użytkownik Yarro napisał: > Witam, > > W wielkim uproszczeniu struktura danych jest nastepujaca (2 tabele): > > transport > ========= > nr_transportu int (primary key, not null) > opis_transportu varchar(30) > data_wyjazdu datetime > nr_zamowienia varchar(10) (null mozliwy) > > zamowienia > ========== > nr_zamowienia varchar(10) (primary key, not null) > opis_zamowienia varchar(30) > nr_transportu int > > -------------------------------------------------- > w bazie MySQL 4.1.19 (win) jest: > zamowienia: 1400 rekordow > transporty: 800 rekordow > > Dopiero jak znany jest nr_transportu dla konkretnego zamowienia updotowana > jest tabela zamowienia gdzie w pole nr_transportu wpisujemy numer > transportu. Sa wiec zamowienia, ktrore w polu nr_transportu maja NULL. > > Chce wybrac wszystkie nr transportu (ktore wyjechaly) wraz z infor z tabeli > zamowienia ale konicznie > musza sie na liscie pojawic rowniez transporty, ktore nie maja przypisanych > numerow transportu w polu > nr_transportu: > > select > tra.nr_transportu, > zam.nr_zamowienia > from > (transporty tra LEFT JOIN zamowienia zam on > tra.nr_transportu=zam.nr_transportu) > WHERE tra.data_wyjazdu is not null > order by tra.nr_transportu desc; > > w rezultacie otrzymuje okolo 290 rekordow ale przetwarzanie tego zapytania > trwa okolo 6-7 sekund. > > Te dwie tabelki wrzucilem do MS ACCESS. Z reki wpisalem dokladnie to samo > zamowienia i na tym samym kompie czas wykonywania jest bardzo krotki: > rezultaty pojawiaja sie natychmiast po odpaleniu kwerendy !!! > > Dlaczego LEFT JOIN jest w MySQL taki wolny (jak na chwile zamienilem go na > INNER JOIN zapytanie wykonalo sie w Mysqlu w 0,01 sec). Skoro Access > poradzil sobie z tym zapytaniem w ułamek sekundy to co zrobic aby tak samo > szybko działało ono w MYSQL. > > Pozdrawiam > Yarro > > > > Witam, wg mojej wiedzy Twój indeks po którym chcesz przypisywać do siebie wyniki z obu tabel (tj. nr_zamowienia) jest po prostu nietrafiony. Uznałeś, że będzie to varchar(). Ten typ pola jest "straszelnie" długo przetwarzany i prawdopodobnie stąd wynika prędkość przetwarzania. Proponuje zastanowić się nad zmianą typu choćby na char i zdaje się, że będzie o wieeeeele szybciej....
pozdrawiam Artur
Artur Muszynski - 02-08-2006 00:06
> wg mojej wiedzy Twój indeks po którym chcesz przypisywać do siebie > wyniki z obu tabel (tj. nr_zamowienia) jest po prostu nietrafiony. > Uznałeś, że będzie to varchar(). Ten typ pola jest "straszelnie" długo > przetwarzany i prawdopodobnie stąd wynika prędkość przetwarzania. > Proponuje zastanowić się nad zmianą typu choćby na char i zdaje się, > że będzie o wieeeeele szybciej....
Pierwsze słyszę. Nullowalność to owszem, ma jakiś wpływ na wydajność.
artur
Yarro - 02-08-2006 00:48
Użytkownik "Artur Gancarz" <einstein@agh.edu.pl> napisał w wiadomości news:eal712$pmb$1@news.agh.edu.pl... > Użytkownik Yarro napisał: >> Witam, >> >> W wielkim uproszczeniu struktura danych jest nastepujaca (2 tabele): >> >> transport >> ========= >> nr_transportu int (primary key, not null) >> opis_transportu varchar(30) >> data_wyjazdu datetime >> nr_zamowienia varchar(10) (null mozliwy) >> >> zamowienia >> ========== >> nr_zamowienia varchar(10) (primary key, not null) >> opis_zamowienia varchar(30) >> nr_transportu int >> >> -------------------------------------------------- >> w bazie MySQL 4.1.19 (win) jest: >> zamowienia: 1400 rekordow >> transporty: 800 rekordow >> >> Dopiero jak znany jest nr_transportu dla konkretnego zamowienia >> updotowana >> jest tabela zamowienia gdzie w pole nr_transportu wpisujemy numer >> transportu. Sa wiec zamowienia, ktrore w polu nr_transportu maja NULL. >> >> Chce wybrac wszystkie nr transportu (ktore wyjechaly) wraz z infor z >> tabeli >> zamowienia ale konicznie >> musza sie na liscie pojawic rowniez transporty, ktore nie maja >> przypisanych >> numerow transportu w polu >> nr_transportu: >> >> select >> tra.nr_transportu, >> zam.nr_zamowienia >> from >> (transporty tra LEFT JOIN zamowienia zam on >> tra.nr_transportu=zam.nr_transportu) >> WHERE tra.data_wyjazdu is not null >> order by tra.nr_transportu desc; >> >> w rezultacie otrzymuje okolo 290 rekordow ale przetwarzanie tego >> zapytania >> trwa okolo 6-7 sekund. >> >> Te dwie tabelki wrzucilem do MS ACCESS. Z reki wpisalem dokladnie to samo >> zamowienia i na tym samym kompie czas wykonywania jest bardzo krotki: >> rezultaty pojawiaja sie natychmiast po odpaleniu kwerendy !!! >> >> Dlaczego LEFT JOIN jest w MySQL taki wolny (jak na chwile zamienilem go >> na >> INNER JOIN zapytanie wykonalo sie w Mysqlu w 0,01 sec). Skoro Access >> poradzil sobie z tym zapytaniem w ułamek sekundy to co zrobic aby tak >> samo >> szybko działało ono w MYSQL. >> >> Pozdrawiam >> Yarro >> >> >> >> > Witam, > wg mojej wiedzy Twój indeks po którym chcesz przypisywać do siebie wyniki > z obu tabel (tj. nr_zamowienia) jest po prostu nietrafiony. Uznałeś, że > będzie to varchar(). Ten typ pola jest "straszelnie" długo przetwarzany i > prawdopodobnie stąd wynika prędkość przetwarzania. > Proponuje zastanowić się nad zmianą typu choćby na char i zdaje się, że > będzie o wieeeeele szybciej....
Zauważ, że pola łącze po nr_transportu, który jest typu int.
> > pozdrawiam > Artur
Artur Gancarz - 02-08-2006 00:48
Użytkownik Artur Muszynski napisał: >> wg mojej wiedzy Twój indeks po którym chcesz przypisywać do siebie >> wyniki z obu tabel (tj. nr_zamowienia) jest po prostu nietrafiony. >> Uznałeś, że będzie to varchar(). Ten typ pola jest "straszelnie" długo >> przetwarzany i prawdopodobnie stąd wynika prędkość przetwarzania. >> Proponuje zastanowić się nad zmianą typu choćby na char i zdaje się, >> że będzie o wieeeeele szybciej.... > > > Pierwsze słyszę. Nullowalność to owszem, ma jakiś wpływ na wydajność. > > artur > Hello, a jednak... pole typu varchar zostają zapisywane w wolnych miejscach na dysku, gdyż: 1) są zmiennej długości (pierwszy wpis jest oczywiście w miejscu reszty danych z rekordu) 2) aktualizacja pola, a zwłaszcza jego wydłużenie powoduje, że dane do tego pola są "wrzucane" w wolne miejsce, oznacza to ni mniej ni więcej tylko dwukrojną "jadę" głowicą dysku aby odczytać jeden rekord, czyli w skrajnych przypadkach ok. 2 razy dłużej czytanie
a oprócz tego: 3) zmienne znakowe są wielokrotnie dłużej przetwarzane niż liczbowe
Nie zmienia to jednak faktu, że się pomyliłem i napisałem, że łaczenie tablej jest polem nr_zamowienia co jest błędne i nie przystaje do rzeczywistości Wobec treści w powyższym zdaniu niestety nie wiem, dlaczego aż tak długo przetwarza.
Artur
Artur Gancarz - 02-08-2006 00:48
Użytkownik Yarro napisał: > Witam, > > W wielkim uproszczeniu struktura danych jest nastepujaca (2 tabele): > > transport > ========= > nr_transportu int (primary key, not null) > opis_transportu varchar(30) > data_wyjazdu datetime > nr_zamowienia varchar(10) (null mozliwy) > > zamowienia > ========== > nr_zamowienia varchar(10) (primary key, not null) > opis_zamowienia varchar(30) > nr_transportu int > > -------------------------------------------------- > w bazie MySQL 4.1.19 (win) jest: > zamowienia: 1400 rekordow > transporty: 800 rekordow > > Dopiero jak znany jest nr_transportu dla konkretnego zamowienia updotowana > jest tabela zamowienia gdzie w pole nr_transportu wpisujemy numer > transportu. Sa wiec zamowienia, ktrore w polu nr_transportu maja NULL. > > Chce wybrac wszystkie nr transportu (ktore wyjechaly) wraz z infor z tabeli > zamowienia ale konicznie > musza sie na liscie pojawic rowniez transporty, ktore nie maja przypisanych > numerow transportu w polu > nr_transportu: > > select > tra.nr_transportu, > zam.nr_zamowienia > from > (transporty tra LEFT JOIN zamowienia zam on > tra.nr_transportu=zam.nr_transportu) > WHERE tra.data_wyjazdu is not null > order by tra.nr_transportu desc; > > w rezultacie otrzymuje okolo 290 rekordow ale przetwarzanie tego zapytania > trwa okolo 6-7 sekund. > > Te dwie tabelki wrzucilem do MS ACCESS. Z reki wpisalem dokladnie to samo > zamowienia i na tym samym kompie czas wykonywania jest bardzo krotki: > rezultaty pojawiaja sie natychmiast po odpaleniu kwerendy !!! > > Dlaczego LEFT JOIN jest w MySQL taki wolny (jak na chwile zamienilem go na > INNER JOIN zapytanie wykonalo sie w Mysqlu w 0,01 sec). Skoro Access > poradzil sobie z tym zapytaniem w ułamek sekundy to co zrobic aby tak samo > szybko działało ono w MYSQL. > > Pozdrawiam > Yarro > > > > Witaj, wymyśliłem jeszcze jedną rzecz, ale nieco naciągane to jest, bo pewnie aż tak wolno by nie robił. Generalnie łączysz do pierwszej tabeli z transportami tabelę z zamówieniami. Ale... dołączając do tabeli nie korzystasz z kluczy (no i indeksów), bo do pola nr_transportu z tabeli transporty (który jest kluczem) dołaczasz tabelę zamówienia za pomocą pola nr_transportu, które w tej tabeli nie ma ani klucza, ani indeksu. To może być przyczyna wolnej pracy, bo silnik bazy przegląda cała tabelę i niestety nie ma jej nigdzie posortowanej wg tego pola więc wyszukuje na "ślepo". Może dodanie indeksu wystarczy?
Drugim rozwiązaniem jest połączenie w drugą stronę, tj.
select tra.nr_transportu, zam.nr_zamowienia from (zamowienia zam LEFT JOIN transporty tra on tra.nr_transportu=zam.nr_transportu) WHERE tra.data_wyjazdu is not null order by tra.nr_transportu desc;
Nie mam tej bazy, więc nie wiem, jak zadziała, ale chyba powinno. Zaletą jest powyżej opisane wykorzystanie klucza głównego tabeli "transport".
ciekaw jestem, czy przyspieszyło?
Artur
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
[mysql] =?ISO-8859-2?Q?Za=E6mienie=2E=2E=2E_jak_wy=B6wietli=E6?==?ISO-8859-2?Q?=2E=2E=2E?=
[mysql] =?ISO-8859-2?Q?wielko=B6=E6_bazy_a_stabilno=B6=E6=2C?==?ISO-8859-2?Q?_podzia=B3_du=BFej_bazy_a_powi=B1zania_tabel?=
[MySQL] =?ISO-8859-2?Q?Wy=B6wietlenie_kolejnej_pozycji=2C_?==?ISO-8859-2?Q?jak=B1_mia=B3by_dany_rekord=2C_gdybym_czyta=B3 _?==?ISO-8859-2?Q?wg_konkretnych_kryteri=F3w=2E_Da_si=EA_=3F?=
[mysql 4.0.x] przenoszenie kolum =?ISO-8859-2?Q?mi=EAdzy_bazam?==?ISO-8859-2?Q?i_cd_=2E=2E=2E_?=
[MySQL] =?ISO-8859-2?Q?z=B3=B1czenie_tabeli_u=BFytkownik_i?==?ISO-8859-2?Q?_zdj=EAcia_z_wyborem_zdj=EAcia_domy=B6lnego?=
[MySQL] Jak =?ISO-8859-2?Q?wpisa=E6_do_tabeli_pozycje_dl?==?ISO-8859-2?Q?a_wierszy_gdybym_te_wiersze_wybiera=B3_w_ok?== ?ISO-8859-2?Q?re=B6lonej_kolejno=B6ci_=3F?=
Gdzie MySQL 4.1, a gdzie 5.0?
[MySQL 4.0...4.1] zabezpieczenie przed =?ISO-8859-2?Q?jednoczesn?==?ISO-8859-2?Q?=B1_edycj=B1?=
[MS SQL] "set names" (mySQL) w MS SQL
[mysql 5.x] jak =?ISO-8859-2?Q?zrealizowa=E6_zapytanie=3F_cz?==?ISO-8859-2?Q?yli_podzapytanie_i_wi=EAcej_ni=BF_jeden_rz=B1? ==?ISO-8859-2?Q?d_wynik=F3w?=
zanotowane.pldoc.pisz.plpdf.pisz.plautwywalczyl.opx.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|