一. 关联查询执行流程
总的来说,mysql认为任何一个查询都是一次关联,并不仅仅是一个查询需要用到两个表匹配才叫关联。
所以,在mysql中,每一个查询,每一个片段(包括子查询,甚至单表select)都可能是关联。
所以,理解mysql如何执行关联查询至关重要,先来看一个union的例子,对于union,mysql先将一系列的单个查询结果放到一个临时表中,
然后再重新读出临时表数据来完成union,在mysql的概念中,每个查询都是一次关联,所以读取结果临时表也是一次关联。
首先MySQL优化器要确定以谁为驱动表,也就是说以哪个表为基准,在处理此类问题时,MySQL优化器采用了简单粗暴的解决方法:
哪个表的结果集小,就以哪个表为驱动表,当然MySQL优化器实际的处理方式会复杂许多
如:
mysql在from子句中遇到子查询,先执行子查询并将结果放到一个临时表中,然后将这个临时表当作一个普通表对待(正如其名:派生表),
mysql在执行union查询时也使用类似的临时表,在遇到右外连接是,mysql将其改写成等价的左外连接,换而言之,当前版本的mysql会将所有的查询类型都换换成类似的执行计划,
不过,不是所有的查询都可以转换成上面的形式,如:全外连接就无法通过嵌套循环和回溯的方式完成,这也是mysql并不支持全外连接的原因。
执行计划:
和很多其他关系数据库不同,mysql并不会生成查询字节码来执行查询,mysql生成查询的一棵指令树,
然后通过存储引擎执行完成这棵指令树并返回结果,最终的执行计划包含了重构查询的全部信息,如对某个查询执行explain extended后,
再执行show warnings,就可以查看到重构的查询。 mysql总是从一个表开始一直嵌套循环,回溯完成所有表的关联。
所以,mysql的执行计划是一棵左侧深度优先的树,然后回溯到上一层关联:
关联查询优化器:
mysql优化器最重要的一部分就是关联查询优化,它决定了多个表关联时的顺序,通常多表关联的时候,
可以有多种不同的关联顺序来获得相同的执行效果,关联查询优化器则通过评估不同顺序时的成本来选择一个代价最小的关联顺序。
二.优化
关于straight_join:
straight_join实现强制多表的载入顺序,从左到右,如:
...A straight_join B on A.name = B.name
straight_join完全等同于inner join 只不过,join语法是根据“哪个表的结果集小,就以哪个表为驱动表”来决定谁先载入的,而straight_join 会强制选择其左边的表先载入。
注意:
总的来说STRAIGHT_JOIN只适用于内连接,因为left join、right join已经知道了哪个表作为驱动表,哪个表作为被驱动表,
比如left join就是以左表为驱动表,right join反之,而STRAIGHT_JOIN就是在内连接中使用,而强制使用左表来当驱动表,
所以这个特性可以用于一些调优,强制改变mysql的优化器选择的执行计划。
但是往往在分析mysql处理性能时,如(Explain),如果发现mysql在载入顺序不合理的情况下,可以使用这个语句,但往往mysql能够自动的分析并处理好。