飞利浦·斯塔克|庖丁解牛|图解 MySQL 8.0 优化器查询转换篇( 七 )


该函数将条件下推到derived tables , 详细见WL#8084 - Condition pushdown to materialized derived table 。
root:testset optimizer_switch = 'derived_merge=off'; // 关闭dervied_merge 测试下推能力Query OK 0 rows affected (0.00 sec)root:testEXPLAIN FORMAT=tree SELECT * FROM (SELECT c1c2 FROM t1) as dt WHERE c110;+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -Table scan on dt (cost=2.51..2.51 rows=1) -Materialize (cost=2.96..2.96 rows=1) -Filter: (t1.c110) (cost=0.35 rows=1) -Table scan on t1 (cost=0.35 rows=1) |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 过程如下:
遍历derived table列表 , 判断是否可以下推(can_push_condition_to_derived) , 如果包括下面的情况则不能下推: Derived table有UNION Derived table有LIMIT Derived table不能是outer join中的内表 , 会导致更多NULL补偿的行 不能是CTE包含的Derived table 创建可以下推到的Derived table的where cond(Condition_pushdown::make_cond_for_derived) 保留剩余不能下推的条件(Condition_pushdown::get_remainder_cond) Top-down递归调用push_conditions_to_derived_tables 详细图解该过程如下:

三 综述 两篇文章重点介绍了下优化器的基于规则的优化部分 , 并没有涉及更多的基于代价的优化 , 可以看到对于直接运用规则优化带来执行的加速 , 那么可以直接转换 , 尤其是对于查询结构上面的变化类转换 , 如merge_derived 。 对于运用规则优化无法判断是否带来执行的加速 , 那么优化器会保留一些临时结构 , 为后续的代价估算提供更多选择 , 如IN/EXIST/Materialized转换 。 当然还有一些 , 又改变查询结构又无法判定是否规则转换带来的执行加速 , MySQL目前还不支持 。 文章虽然详尽 , 但无法覆盖全部情况 , 也是为了抛砖引玉 , 还需要读者自己通过调试的方法更进一步了解某一类SQL的具体过程 。
四 参考资料 《MySQL 8.0 Server层最新架构详解》
《WL#13520: Transform correlated scalar subqueries》
《WL#8084 - Condition pushdown to materialized derived table》
《WL#2980: Subquery optimization: Semijoin》
WL#3740: Subquery optimization: Semijoin: Pull-out of inner tables WL#3741: Subquery optimization: Semijoin: Duplicate elimination strategy WL#3750: Subquery optimization: Semijoin: First-match strategy WL#3751: Subquery optimization: Semijoin: Inside-out strategy 《WL#4389: Subquery optimizations: Make IN optimizations also handle EXISTS》
《WL#4245: Subquery optimization: Transform NOT EXISTS and NOT IN to anti-join》
《WL#2985: Perform Partition Pruning of Range conditions》《MySQL · 源码分析 · Semi-join优化执行代码分析》《MySQL·源码分析·子查询优化源码分析》《Optimizing Subqueries Derived Tables View References and Common Table Expressions》
本文为阿里云原创内容 , 未经允许不得转载 。