![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 11 Pomógł: 0 Dołączył: 29.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Witam,
mam dosc spora baze (ok. 3 mln rekordow) z firmami w ktorej pojawil mi sie problem przy zapytaniu ktore pobiera dane firmy wg. okreslonej branzy, a wyniki sortuje po polu liczbowym - 'priorytet'. Tabele mam w innoDB a czas query siega 20sekund: Oto zapytanie:
Budowa tabeli firmy:
Budowa tabeli zlaczeniowej branz:
Wynik explain zapytania pokazuje taki rezultat (niepokojacy dla tabeli firma_branza):
Czy ktos pomoze w probie ustawienia odpowiednich indeksow zeby to dzialanie zoptymalizowac ? |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 282 Pomógł: 89 Dołączył: 12.04.2011 Ostrzeżenie: (0%) ![]() ![]() |
Czym różni się LEFT JOIN od INNER JOINa? LEFT JOIN zwraca również te rekordy z lewej tabeli, dla których nie ma rekordów w prawej tabeli spełniających warunek złączenia. Wtedy pola z drugiej tabeli przyjmują wartość NULL. W przypadku zapytania ze startera wątku dodatkowo ograniczamy rekordy z prawej tabeli warunkiem id_branza_1 = 455, czyli wcale nie chcemy niczego co by było NULL.
Wniosek jest taki, że nasz LEFT JOIN przy tym warunku staje się tak naprawdę INNER JOINem i optimizer tak właśnie go przepisał, skoro pierwsza tabela w wynikach explain jest właśnie prawa. Prawdopodobnie widząc ten dość 'silny' warunek, bo w końcu porównujemy pole z jedną, konkretną, dosyć wysoką wartością optimizer spodziewał się, że szybciej będzie zacząć od tabeli firmy_branza, ograniczyć rekordy do tych, które ten warunek spełniają, po czym połączyć to z tabelą firmy, sprawdzić status i posortować to co zostanie po priorytecie. Stąd taki a nie inny plan wykonania tego zapytania. Tylko że okazuje się, że do sortowania mamy 129168 rekordów w tymczasowej tabeli, co musi być bolesne, nie ma bata, a musimy posortować wszystkie, bo przecież najwyższy priorytet może być w ostatnim rekordzie. Biorąc pod uwagę jednak stosunkowo małą liczbie rekordów, które chcemy obejrzeć - LIMIT 20, a także fakt, że są to pierwsze rekordy - OFFSET 0, możemy się spodziewać, że gdybyśmy zaczęli od tabeli firmy, znajdując po indeksie status_priorytet najwyższe priorytety z właściwym statusem i sprawdzali czy połączone rekordy z tabeli firmy_branza mają id_branza_1 = 455 (a szansa na to jest niemała, akurat dla tej właśnie wartości), to moglibyśmy szybko przerwać, po znalezieniu 20 takich rekordów. Oczywiście gdyby tego limitu nie było, albo offset byłby wysoki, albo firm z tej branży byłoby mało, wtedy oryginalny plan wykonania byłby optymalny, w tym jednak konkretnym przypadku mamy do czynienia z klasyczną sytuacją, w której optimizer wybrał złą kolejność złączenia i trzeba mu dopomóc. Podsumowując - możemy spróbować zapytania:
|
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 11 Pomógł: 0 Dołączył: 29.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Tutaj mam najlepszy rezultat. Musze poprzerabiac moje zapytania w tym kierunku. Dzieki wielkie. |
|
|
![]() ![]() |
![]() |
Aktualny czas: 17.10.2025 - 12:32 |