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
Czy możesz wyświetlić również zapytanie? –
@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
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. –