13.2.10.10 Оптимизация подзапросов
Разработка продолжается, поэтому никакие советы по оптимизации не гарантируют долговременной эффективности. В следующем списке приведены некоторые интересные приёмы, которые можно попробовать. См. также Раздел 8.2.2, «Оптимизация подзапросов, производных таблиц и ссылок на представления».
-
Используйте подзапросы, которые влияют на количество или порядок строк в подзапросе. Например:
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
-
Замените соединение подзапросом. Например, попробуйте это:
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN ( SELECT column1 FROM t2);
Вместо этого:
SELECT DISTINCT t1.column1 FROM t1, t2 WHERE t1.column1 = t2.column1;
Некоторые подзапросы могут быть преобразованы в соединения для совместимости со старыми версиями MySQL, которые не поддерживают подзапросы. Однако в некоторых случаях преобразование подзапроса в соединение может улучшить производительность. См. Раздел 13.2.10.11, «Переписывание подзапросов как соединений».
-
Переместите предложения извне внутрь подзапроса. Например, используйте этот запрос:
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
Вместо этого запроса:
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
Для другого примера используйте этот запрос:
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
Вместо этого запроса:
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
-
Используйте подзапрос на строки вместо коррелированного подзапроса. Например, используйте этот запрос:
SELECT * FROM t1 WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
Вместо этого запроса:
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1 AND t2.column2=t1.column2); Используйте
NOT (a = ANY (...))вместоa <> ALL (...).Используйте
x = ANY (вместоtable containing (1,2))x=1 OR x=2.Используйте
= ANYвместоEXISTS.-
Для некоррелированных подзапросов, которые всегда возвращают одну строку,
INвсегда медленнее, чем=. Например, используйте этот запрос:SELECT * FROM t1 WHERE t1.
col_name= (SELECT a FROM t2 WHERE b =some_const);Вместо этого запроса:
SELECT * FROM t1 WHERE t1.
col_nameIN (SELECT a FROM t2 WHERE b =some_const);
Эти приёмы могут привести к ускорению или замедлению работы программ. С помощью функций MySQL, таких как функция BENCHMARK(), можно получить представление о том, что помогает в вашей конкретной ситуации. См. Раздел 12.15, «Функции информации».
Некоторые оптимизации, которые выполняет сам MySQL:
MySQL выполняет некоррелированные подзапросы только один раз. Используйте
EXPLAIN, чтобы убедиться, что данный подзапрос действительно некоррелированный.MySQL переписывает
IN,ALL,ANYиSOMEподзапросы, пытаясь воспользоваться возможностью индексирования столбцов списка выбора в подзапросе.-
MySQL заменяет подзапросы следующей формы функцией поиска по индексу, которую
EXPLAINописывает как особый тип соединения (unique_subqueryилиindex_subquery):... IN (SELECT
indexed_columnFROMsingle_table...) -
MySQL улучшает выражения следующей формы с помощью выражения, включающего
MIN()илиMAX(), если не задействованы значенияNULLили пустые множества:value{ALL|ANY|SOME} {> | < | >= | <=} (uncorrelated subquery)Например, эта
WHEREфраза:WHERE 5 > ALL (SELECT x FROM t)
может быть интерпретирована оптимизатором следующим образом:
WHERE 5 > (SELECT MAX(x) FROM t)
См. также MySQL Internals: How MySQL Transforms Subqueries.
© 2025 Oracle
Licensed under the GPLv2 License.