Spec-Zone.ru › MySQL 8.4

10.2.2.5 Оптимизация вынесения условия производной таблицы

MySQL поддерживает вынесение условия производной таблицы для подходящих подзапросов. Для запроса, такого как SELECT * FROM (SELECT i, j FROM t1) AS dt WHERE i > constant, во многих случаях возможно вынести внешнее условие WHERE в производную таблицу, что в данном случае приводит к SELECT * FROM (SELECT i, j FROM t1 WHERE i > constant) AS dt. Когда производную таблицу нельзя объединить с внешним запросом (например, если производная таблица использует агрегацию), вынесение внешнего условия WHERE в производную таблицу должно уменьшить количество обрабатываемых строк и, следовательно, ускорить выполнение запроса.

Внешние условия WHERE могут быть вынесены в материализованные таблицы производных при следующих обстоятельствах:

  • Если производная таблица не использует агрегатные или оконные функции, то внешнее условие WHERE может быть вынесено в нее непосредственно. Это включает условия WHERE, имеющие несколько предикатов, соединенных операторами `И`, `ИЛИ` или обоими.

    Например, запрос SELECT * FROM (SELECT f1, f2 FROM t1) AS dt WHERE f1 < 3 AND f2 > 11 переписывается как SELECT f1, f2 FROM (SELECT f1, f2 FROM t1 WHERE f1 < 3 AND f2 > 11) AS dt.

  • Если производная таблица имеет GROUP BY и не использует оконные функции, то внешнее условие WHERE, ссылающееся на один или несколько столбцов, которые не являются частью GROUP BY, может быть вынесено в производную таблицу как условие HAVING.

    Например, SELECT * FROM (SELECT i, j, SUM(k) AS sum FROM t1 GROUP BY i, j) AS dt WHERE sum > 100 после оптимизации вынесения условия производной таблицы переписывается как SELECT * FROM (SELECT i, j, SUM(k) AS sum FROM t1 GROUP BY i, j HAVING sum > 100) AS dt.

  • Если производная таблица использует GROUP BY, а столбцы во внешнем условии WHERE являются GROUP BY столбцами, то условия WHERE, ссылающиеся на эти столбцы, могут быть вынесены непосредственно в производную таблицу.

    Например, запрос SELECT * FROM (SELECT i,j, SUM(k) AS sum FROM t1 GROUP BY i,j) AS dt WHERE i > 10 переписывается как SELECT * FROM (SELECT i,j, SUM(k) AS sum FROM t1 WHERE i > 10 GROUP BY i,j) AS dt.

    В случае, когда внешнее условие WHERE содержит предикаты, ссылающиеся на столбцы, которые являются частью GROUP BY, а также предикаты, ссылающиеся на столбцы, которые не являются частью GROUP BY, предикаты первого типа выносятся как условия WHERE, а предикаты второго типа – как условия HAVING. Например, в запросе SELECT * FROM (SELECT i, j, SUM(k) AS sum FROM t1 GROUP BY i,j) AS dt WHERE i > 10 AND sum > 100 предикат i > 10 в внешнем условии WHERE ссылается на столбец GROUP BY, а предикат sum > 100 не ссылается ни на один столбец GROUP BY. Таким образом, оптимизация вынесения условия производной таблицы приводит к переписыванию запроса, примерно так, как показано здесь:

    SELECT * FROM (
        SELECT i, j, SUM(k) AS sum FROM t1
            WHERE i > 10
            GROUP BY i, j
            HAVING sum > 100
        ) AS dt;
    

Для включения вынесения условия производной таблицы переменная системы optimizer_switch должна быть установлена в значение, включающее флаг derived_condition_pushdown (добавлено в этом релизе) в значение on, что является значением по умолчанию. Если эта оптимизация отключена значением optimizer_switch, ее можно включить для конкретного запроса, используя подсказку оптимизатора DERIVED_CONDITION_PUSHDOWN. Для отключения оптимизации для данного запроса используйте подсказку оптимизатора NO_DERIVED_CONDITION_PUSHDOWN.

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

  • Оптимизация вынесения условия производной таблицы может быть применена к UNION запросам, с исключениями:

    • Вынесение условия не может быть использовано с запросом UNION, если любая материализованная производная таблица, которая является частью UNION, является рекурсивным общим табличным выражением (см. Рекурсивные общие табличные выражения).

    • Условие, содержащее недетерминированные выражения, не может быть вынесено в производную таблицу.

  • Производная таблица не может использовать предложение LIMIT.

  • Условия, содержащие подзапросы, не могут быть вынесены.

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

  • Если материализованная производная таблица является общим табличным выражением, условия не выносятся в нее, если она ссылается несколько раз.

  • Условия, использующие параметры, могут быть вынесены, если условие имеет вид derived_column > ?. Если производный столбец во внешнем условии WHERE является выражением, содержащим ? в базовой производной таблице, это условие не может быть вынесено.

  • Для запроса, в котором условие относится к таблицам представления, созданного с помощью ALGORITHM=TEMPTABLE, а не к самому представлению, множественное равенство не распознается на этапе разрешения, и, следовательно, условие не может быть вынесено. Это происходит потому, что при оптимизации запроса вынесение условия происходит на этапе разрешения, в то время как распространение множественного равенства происходит во время оптимизации.

    Это не проблема в таких случаях для представления, использующего ALGORITHM=MERGE, где равенство может быть распространено, а условие вынесено.

  • Условие не может быть вынесено, если список SELECT производной таблицы содержит какие-либо присваивания переменным пользователя.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/derived-condition-pushdown-optimization.html

Spec-Zone.ru

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