Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

10.2.2.5 派生条件下推优化

MySQL支持派生条件下推优化的子查询。对于查询如 SELECT * FROM (SELECT i, j FROM t1) AS dt WHERE i > 常量, 在许多情况下,可以将外部 WHERE 条件下推到派生表中,在这种情况下,结果将是 SELECT * FROM (SELECT i, j FROM t1 WHERE i > 常量) AS dt。当派生表不能合并到外部查询中(例如,如果派生表使用聚合函数),将外部 WHERE 条件下推到派生表中将减少需要处理的行数,从而加速查询的执行。

外部 WHERE 条件可以在以下情况下下推到派生物化表中:

  • 当派生表不使用聚合或窗口函数时,外部 WHERE 条件可以直接下推到派生表中。这包括使用 ANDOR 或两者的多个谓词连接的 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 中,外部 WHERE 子句中的谓词 i > 10 引用了 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 查询中的任何物化派生表是递归公共表表达式(见 递归公共表表达式),则不能使用条件推送。

    • 包含非确定性表达式的条件不能被推送到派生表中。

  • 派生表不能使用 LIMIT 子句。

  • 包含子查询的条件不能被推送。

  • 如果派生表是外连接的内部表,则不能使用该优化。

  • 如果物化派生表是一个公共表表达式,并且它被多次引用,则不能将条件推送到它。

  • 如果条件使用参数,可以将其推送到派生表中,例如 derived_column > ?。如果派生列在外部 WHERE 条件中是一个包含 ? 的表达式,则该条件不能被推送。

  • 对于一个条件位于使用 ALGORITHM=TEMPTABLE 创建的视图的表上的查询,而不是在视图本身上,多重相等性在解析时不能被识别,因此条件不能被推送下去。这是因为,在查询优化时,条件推送发生在解析阶段,而多重相等性传播发生在优化阶段。

    对于使用 ALGORITHM=MERGE 的视图,这不是一个问题,因为相等性可以传播并且条件可以被推送下去。

  • 如果派生表的 SELECT 列表包含任何用户变量的赋值,则条件不能被推送下去。