Например, скажем, мой код на стороне клиента генерирует запрос с номером в предложении where.
Иногда число приводит к невозможному предложению where, в противном случае оно не будет.
Как использовать объяснение, чтобы проверить, насколько хорошо оптимизирован запрос?
MySQL
создает разные планы запросов для разных значений связанных параметров.
В этой статье вы можете прочитать список того, когда оптимизатор MySQL
делает что:
Action When
Query parse PREPARE
Negation elimination PREPARE
Subquery re-writes PREPARE
Nested JOIN simplification First EXECUTE
OUTER->INNER JOIN conversions First EXECUTE
Partition pruning Every EXECUTE
COUNT/MIN/MAX elimination Every EXECUTE
Constant subexpression removal Every EXECUTE
Equality propagation Every EXECUTE
Constant table detection Every EXECUTE
ref access analysis Every EXECUTE
range/index_merge analysis and optimization Every EXECUTE
Join optimization Every EXECUTE
В этом списке отсутствует еще одна вещь.
MySQL
может перестраивать план запроса на каждую JOIN
итерацию : такой называется range checking for each record
.
Если у вас есть составной индекс для таблицы:
CREATE INDEX ix_table2_col1_col2 ON table2 (col1, col2)
и такой запрос:
SELECT *
FROM table1 t1
JOIN table2 t2
ON t2.col1 = t1.value1
AND t2.col2 BETWEEN t1.value2_lowerbound AND t2.value2_upperbound
, MySQL
НЕ будет использовать индекс RANGE
доступ от (t1.value1, t1.value2_lowerbound)
до (t1.value1, t1.value2_upperbound)
. Вместо этого он будет использовать индекс REF
access для (t1.value)
и просто отфильтровывает неправильные значения.
Но если переписать запрос так:
SELECT *
FROM table1 t1
JOIN table2 t2
ON t2.col1 <= t1.value1
AND t2.col1 >= t2.value1
AND t2.col2 BETWEEN t1.value2_lowerbound AND t2.value2_upperbound
, затем MySQL
перепроверит индекс RANGE
access для каждой записи из table1
и решит, использовать ли RANGE
доступ на лету.
Вы можете прочитать об этом в этих статьях в моем блоге:
Все эти вещи используют RANGE CHECKING FOR EACH RECORD
Возвращаясь к вашему вопросу: нет никакого способа определить, какой план будет MySQL
использовать для каждой данной константы, поскольку нет плана до того, как константа будет задана.
К сожалению, нет способа заставить MySQL
использовать один план запроса для каждого значения связанного параметра.
Вы можете контролировать порядок JOIN
и INDEX
, выбранные с помощью предложений STRAIGHT_JOIN
и FORCE INDEX
, но они не будут принудительно определять определенный путь доступа к индексу или запрещать IMPOSSIBLE WHERE
.
С другой стороны, для всех JOIN
, MySQL
использует только NESTED LOOPS
. Это означает, что если вы построите правильный JOIN
порядок или выберете правильные индексы, MySQL
, вероятно, выиграет от всех IMPOSSIBLE WHERE
.