2012-04-13 12 views
19

Patrząc na plan zapytania EXPLAIN, jak określić, gdzie najlepiej można optymalizować?Jak zoptymalizować zapytania MySQL na podstawie EXPLAIN planu

Doceniam fakt, że jedną z pierwszych rzeczy, które należy sprawdzić jest to, czy dobre indeksy są używane, ale poza tym jestem trochę zakłopotany. Dzięki próbom i błędom w przeszłości czasami stwierdziłem, że kolejność, w której przeprowadzane są połączenia, może być dobrym źródłem poprawy, ale jak można to ustalić, patrząc na plan wykonania?

Chociaż bardzo chciałbym uzyskać ogólną wiedzę na temat optymalizacji zapytań (sugerowana lektura bardzo ceniona!), Zdaję sobie również sprawę, że często łatwiej jest omawiać konkretne przypadki niż mówić abstrakcyjnie. Ponieważ jestem obecnie walić głową w ścianę z tym jednym, twoje myśli będą mile widziane:

 
id select_type table type  possible_keys key  key_len ref     rows Extra 
1 SIMPLE  S  const PRIMARY,l,p,f4 PRIMARY   2 const      1 Using temporary 
1 SIMPLE  Q  ref  PRIMARY,S  S    2 const     204 Using index 
1 SIMPLE  V  ref  PRIMARY,n,Q  Q    5 const,db.Q.QID   6 Using where; Using index; Distinct 
1 SIMPLE  R1  ref  PRIMARY,L  L    154 const,db.V.VID   447 Using index; Distinct 
1 SIMPLE  W  eq_ref PRIMARY,w  PRIMARY   5 const,db.R.RID,const  1 Using where; Distinct 
1 SIMPLE  R2  eq_ref PRIMARY,L  PRIMARY  156 const,db.W.RID,const  1 Using where; Distinct 

mam rację w interpretacji końcowy wiersz planu wykonania, co następuje:

  • jako jest w pełni dopasowany do klucza podstawowego, tylko jeden wiersz z R2 musi być pobrany na wiersz wyjściowy;
  • Jednak takie wiersze wyjściowe są następnie filtrowane na podstawie niektórych kryteriów, które mają zastosowanie do R2?

Jeśli tak, mój problem polega na filtrowaniu, które występuje w tym ostatnim kroku. Jeśli warunek nie powoduje filtrowania (na przykład WHERE `Col_1_to_3` IN (1,2,3)), zapytanie działa bardzo szybko (~ 50 ms); jeśli jednak warunek ogranicza wybrane wiersze (WHERE `Col_1_to_3` IN (1,2)), zapytanie trwa znacznie dłużej (~ 5s). Jeśli ograniczenie dotyczy pojedynczego meczu (WHERE `Col_1_to_3` IN (1)), optymalizator sugeruje zupełnie inny plan wykonania (który wykonuje marginalnie lepiej niż 5 sekund, ale wciąż jest o wiele gorszy niż 50 ms). Nie wydaje się, że istnieje lepszy indeks, który może być użyty na tej tabeli (biorąc pod uwagę, że jest już w pełni przy użyciu klucza podstawowego, aby zwrócić jeden wiersz na wynik?).

Jak należy interpretować wszystkie te informacje? Czy mam rację, zgadując, że ponieważ takie filtrowanie wyjściowe odbywa się na stole finałowym, który ma zostać połączony, marnuje się znaczny wysiłek w porównaniu do wcześniejszego łączenia się z tabelą i wcześniejszego filtrowania takich wierszy? Jeśli tak, to w jaki sposób należy ustalić, kiedy w planie wykonawczym należy przyłączyć R2?

Podczas gdy opór tym schemacie w całości tutaj zapytanie & (jak ja to naprawdę może wiedzieć, czego szukać, a nie tylko być poinformowani odpowiedź), rozumiem, że to konieczne, aby przejść do dyskusji:

SELECT DISTINCT 
    `Q`.`QID` 
FROM 
    `S` 
    NATURAL JOIN `Q` 
    NATURAL JOIN `V` 
    NATURAL JOIN `R` AS `R1` 
    NATURAL JOIN `W` 

    JOIN `R` AS `R2` ON (
      `R2`.`SID` = `S`.`SID` 
     AND `R2`.`RID` = `R1`.`RID` 
     AND `R2`.`VID` = `S`.`V_id` 
     AND `R2`.`Col_1_to_3` IN (1,2) -- this is where performance suffers! 
    ) 

WHERE 
    AND `S`.`SID` = @x 
    AND `W`.`WID` = @y 
; 

definicja tabeli R jest:

CREATE TABLE `R` (
    `SID` smallint(6) unsigned NOT NULL, 
    `RID` smallint(6) unsigned NOT NULL, 
    `VID` varchar(50) NOT NULL DEFAULT '', 
    `Col_1_to_3` smallint(1) DEFAULT NULL, 
    `T` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`SID`,`RID`,`VID`), 
    KEY `L` (`SID`,`VID`,`Col_1_to_3`), 
    CONSTRAINT `R_f1` FOREIGN KEY (`SID`) REFERENCES `S` (`SID`), 
    CONSTRAINT `R_f2` FOREIGN KEY (`SID`, `VID`) REFERENCES `V` (`SID`, `VID`), 
    CONSTRAINT `R_f3` FOREIGN KEY (`SID`, `VID`, `Col_1_to_3`) REFERENCES `L` (`SID`, `VID`, `LID`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
+0

Czy możesz wyświetlić również zapytanie? –

+0

@MarcusAdams: Nie mam * umysłu *, ale czego byś szukał? Wydaje mi się, że prawdopodobnie dowiem się więcej, jeśli będę wiedział, na co patrzysz ... – eggyal

+0

Odwołujesz się do col_1_to_3, ale nie widzę takiej kolumny w wyniku EXPLAIN. Jeśli potrafisz sformułować pytanie tak, że chodzi tylko o wyjaśnienie, innymi słowy usuń akapity mówiące o zapytaniu, to nie potrzebujemy zapytania, a odpowiedź brzmi "tak". Ogólnie rzecz biorąc, potrzebujemy kwerendy, schematu i wyjaśnienia, inaczej zgadujemy. –

Odpowiedz

13

Zależy co masz zamiar i co jest zapytanie.

Ogólnie, dla każdej linii w wyjaśnić, że ma Using where, trzeba mieć go przy użyciu indeksu (possible keys i keys kolumna). To są twoje filtry i zawierają WHERE i ON. Mając to powiedzieć Using index jest jeszcze lepszy. Oznacza to, że istnieje indeks obejmujący, a MySQL może pobierać dane bezpośrednio z indeksu zamiast odwiedzać wiersz w danych tabeli.

Należy zwrócić uwagę na linie, na których nie ma Using where i zwracana jest duża liczba rzędów.Są to zwracane wartości dla wszystkich wierszy w tabeli. Nie wiem, jakie jest twoje zapytanie, więc nie wiem, czy się tu niepokoić. Spróbuj przefiltrować zestaw wyników, aby zmniejszyć rozmiar i poprawić wydajność.

Generalnie powinieneś unikać wyświetlania Using filesort lub Using temporary, ale są one złe tylko wtedy, gdy ich nie oczekujesz.

Pliki zazwyczaj pojawiają się z klauzulą ​​ZAMÓW. Generalnie chcesz, aby MySQL używał indeksu obejmującego (Using index), aby wiersze były zwracane już w kolejności od serwera. Jeśli nie, MySQL musi zamówić je później, używając filesort.

Using temporary może być zły, gdy odnosi się do tabel pochodnych, ponieważ nie mają indeksów. Wygląda na to, że utworzono tymczasowo tabelę tymczasową z indeksami, więc tutaj nie jest źle. Czasami jedynym twoim wyborem jest użycie wyprowadzonej tabeli, a tym samym Using temporary.

+0

Dzięki Marcus. Przypuszczam, że najbardziej dziwna jest różnica w wydajności wynikająca z filtra na stole finałowym; dlatego wydaje się, że problem nie leży w "liniach, w których ... powraca duża liczba rzędów", które sugerujesz, na które patrzę? – eggyal

Powiązane problemy