Spec-Zone.ru › MySQL 5.7

8.2.2.2 Оптимизация подзапросов с помощью материализации

Оптимизатор использует материализацию для повышения эффективности обработки подзапросов. Материализация ускоряет выполнение запроса, создавая результат подзапроса в виде временной таблицы, обычно в памяти. В первый раз, когда MySQL нуждается в результате подзапроса, он материализует этот результат в временную таблицу. В последующие разы, когда результат требуется, MySQL снова обращается к временной таблице. Оптимизатор может индексировать таблицу с помощью хэш-индекса, чтобы сделать поиск быстрым и недорогим. Индекс содержит уникальные значения, чтобы устранить дубликаты и сделать таблицу меньше.

Материализация подзапросов использует временную таблицу в памяти, если это возможно, переходя к хранению на диске, если таблица становится слишком большой. См. Раздел 8.4.4, «Использование внутренних временных таблиц в MySQL».

Если материализация не используется, оптимизатор иногда переписывает некоррелированный подзапрос как коррелированный подзапрос. Например, следующий IN подзапрос некоррелированный (where_condition включает только столбцы из t2, а не из t1):

SELECT * FROM t1
WHERE t1.a IN (SELECT t2.b FROM t2 WHERE where_condition);

Оптимизатор может переписать это как EXISTS коррелированный подзапрос:

SELECT * FROM t1
WHERE EXISTS (SELECT t2.b FROM t2 WHERE where_condition AND t1.a=t2.b);

Материализация подзапросов с использованием временной таблицы избегает таких переписываний и позволяет выполнить подзапрос только один раз, а не один раз на каждую строку внешнего запроса.

Для использования материализации подзапросов в MySQL должна быть включена системная переменная optimizer_switch с флагом materialization. (См. Раздел 8.9.2, «Переключаемые оптимизации».) При включенном флаге materialization материализация применяется к предикатам подзапросов, которые появляются где угодно (в списке выбора, WHERE, ON, GROUP BY, HAVING или ORDER BY), для предикатов, которые попадают под любой из этих случаев использования:

  • Предикат имеет такой вид, когда ни внешнее выражение oe_i, ни внутреннее выражение ie_i не допускают значение NULL. N равно 1 или больше.

    (oe_1, oe_2, ..., oe_N) [NOT] IN (SELECT ie_1, i_2, ..., ie_N ...)
    
  • Предикат имеет такой вид, когда существует единственное внешнее выражение oe и внутреннее выражение ie. Выражения могут допускать значение NULL.

    oe [NOT] IN (SELECT ie ...)
    
  • Предикат является IN или NOT IN, и результат UNKNOWN (NULL) имеет такое же значение, как результат FALSE.

Следующие примеры иллюстрируют, как требование эквивалентности оценки предикатов UNKNOWN и FALSE влияет на возможность использования материализации подзапросов. Предположим, что where_condition включает только столбцы из t2, а не из t1, так что подзапрос некоррелированный.

Этот запрос подлежит материализации:

SELECT * FROM t1
WHERE t1.a IN (SELECT t2.b FROM t2 WHERE where_condition);

Здесь не имеет значения, возвращает ли предикат IN значение UNKNOWN или FALSE. В любом случае строка из t1 не включается в результат запроса.

Пример, где материализация подзапроса не используется, — это следующий запрос, где t2.b — столбец, допускающий значение NULL:

SELECT * FROM t1
WHERE (t1.a,t1.b) NOT IN (SELECT t2.a,t2.b FROM t2
                          WHERE where_condition);

Следующие ограничения применяются к использованию материализации подзапросов:

  • Типы внутренних и внешних выражений должны совпадать. Например, оптимизатор может использовать материализацию, если оба выражения являются целыми числами или оба являются десятичными числами, но не может, если одно выражение является целым числом, а другое — десятичным.

  • Внутреннее выражение не может быть BLOB.

Использование EXPLAIN с запросом дает некоторое представление о том, использует ли оптимизатор материализацию подзапросов:

  • По сравнению с выполнением запроса без материализации, select_type может измениться с DEPENDENT SUBQUERY на SUBQUERY. Это указывает на то, что для подзапроса, который выполнялся бы один раз на каждую строку внешнего запроса, материализация позволяет выполнить подзапрос только один раз.

  • Для расширенного вывода EXPLAIN отображаемый текст последующего SHOW WARNINGS включает materialize и materialized-subquery.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/subquery-materialization.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API