五 进一步挖掘
1 MySQL仅仅是用半连接/物化/EXISTS策略来优化子查询的吗?
Convert the subquery to a join, or use table pullout and run the query as an inner join between subquery tables and outer tables. Table pullout pulls a table out from the subquery to the outer query.
这表明MySQL是可以把子查询优化为连接操作的(这是一种特例:把半连接进一步优化为连接,需要子查询的目标列为唯一键,如outer_expr IN (SELECT field_primary_key...))。
2 三种优化策略之间的关系
2.1 默认使用半连接进行优化,可以使用“set optimizer_switch='semijoin=off';”命令关闭半连接策略。
2.2 如果半连接参数关闭,则可以使用物化策略或EXISTS策略,使用哪种,由decide_subquery_strategy()函数决定,此函数调用compare_costs_of_subquery_strategies()函数进行两种策略的代价计算,决定选用代价小的优化策略。可以使用“set optimizer_switch='materialization=off'; ”命令关闭物化策略,进而指示MySQL优化器使用EXISTS策略。
3 如何区分是使用了哪种优化策略?
策略名称 | 查询执行计划显示项 | 值 | 说明 |
半连接策略 | SHOW WARNINGS命令显示内容 | semi join | |
物化策略 | select_type | SUBQUERY/SIMPLE | |
SHOW WARNINGS命令显示内容 | <materialize>(query fragment) | 非半连接的物化,即物化策略中的物化 | |
select_type | MATERIALIZED | 被物化策略物化的子查询 | |
EXISTS策略 | select_type | DEPENDENT SUBQUERY | DEPENDENT说明了依赖的关系,EXISTS策略把子查询变为了相关子查询 |