Подзапросы в предложении FROM не могут быть соотнесены подзапросам. Они осуществлены (выполнены, чтобы произвести набор результатов) перед оценкой внешнего запроса, так что они не могут быть оценены на строку внешнего запроса.
Оптимизатор более отлажен для объединений, чем для подзапросов, так что во многих случаях инструкция, применяющая подзапрос, может быть выполнена более эффективно, если Вы переписываете это как объединение.
Исключительная ситуация происходит для случая, где подзапрос IN может быть переписан как объединение SELECT DISTINCT. Пример:
SELECT col FROM t1 WHERE id_col IN (SELECT id_col2 FROM t2 WHERE
Эта инструкция может быть переписана следующим образом:
SELECT DISTINCT col FROM t1, t2 WHERE t1.id_col = t2.id_col AND
Но в этом случае объединение требует операции DISTINCT, и не более эффективно, чем подзапрос.
Возможная будущая оптимизация: MySQL не переписывает порядок объединения для оценки подзапроса. В некоторых случаях подзапрос мог бы быть выполнен более эффективно, если MySQL переписал это как объединение. Это дало бы оптимизатору возможность, чтобы выбрать между большим количеством планов выполнения. Например, это могло бы решать, читать ли одну таблицу или другую первой:
SELECT a FROM outer_table AS ot
WHERE a IN (SELECT a FROM inner_table AS
it WHERE ot.b = it.b);
Для этого запроса MySQL всегда просматривает сначала outer_table, а затем выполняет подзапрос на inner_table для каждой строки. Если outer_table имеет много строк, и inner_table имеет немного строк, запрос, вероятно, не будет работать с такой скоростью как могло бы быть.
Предшествующий запрос мог бы быть переписан подобно этому:
SELECT a FROM outer_table AS ot, inner_table AS it
WHERE ot.a = it.a AND
ot.b = it.b;
В этом случае мы можем просматривать маленькую таблицу (inner_table) и искать строки в outer_table, что будет быстро, если имеется индекс на (ot.a,ot.b).
Возможная будущая оптимизация: соотнесенный подзапрос оценен для каждой строки внешнего запроса. Лучший подход: если внешние значения строки не изменяются с предыдущей строки, чтобы не оценивать подзапрос снова. Вместо этого, используется предыдущий результат.
Возможная будущая оптимизация: подзапрос в предложении FROM оценен, осуществляя результат во временную таблицу, и эта таблица не использует индексы. Это не позволяет использование индексов по сравнению с другими таблицами в запросе, хотя это могло бы быть полезно.
Возможная будущая оптимизация: если подзапрос в предложении FROM походит на просмотр, к которому может применяться объединяющийся алгоритм, переписать запрос и применить объединяющийся алгоритм так, чтобы индексы могли использоваться. Следующая инструкция содержит такой подзапрос:
SELECT * FROM (SELECT * FROM t1 WHERE t1.t1_col) AS _t1, t2 WHERE t2.t2_col;
Инструкция может быть переписана как объединение подобно этому:
SELECT * FROM t1, t2 WHERE t1.t1_col AND t2.t2_col;
Этот тип перезаписи обеспечил бы две выгоды:
Это избегает использования временной таблицы, для которой никакие индексы не могут использоваться. В переписанном запросе оптимизатор может использовать индексы на t1.
Это дает оптимизатору большее количество свободы выбрать между различными планами выполнения. Например, перезапись запроса как объединения позволяет оптимизатору использовать сначала t1 или t2.
Возможная будущая оптимизация: для IN, = ANY, <> ANY, = ALL и <> ALL с не соотнесенными подзапросами использовать в оперативной памяти хэш для результата или временную таблицу с индексом для больших результатов. Пример:
SELECT a FROM big_table AS bt WHERE non_key_field IN
(SELECT non_key_field FROM
В этом случае мы могли бы создавать временную таблицу:
CREATE TABLE t (key (non_key_field))
(SELECT non_key_field FROM
Затем для каждой строки в big_table сделайте поисковую таблицу ключа в t, основываясь на bt.non_key_field.
11.4. Ограничения на Views
Обработка View не оптимизирована:
Невозможно создать индекс на view.
Индексы могут использоваться для обработанных view, используя объединяющий алгоритм. Однако,