MySQL-查询-SQL简化与子查询的物化
目录
条件化简
|
|
外连接消除
具体可以先看连接查询
内连接的驱动表和被驱动表的位置可以相互转换,而左(外)连接和右(外)连接的驱动表和被驱动表是固定的。 这就导致内连接可能通过优化表的连接顺序来降低整体的查询成本,而外连接却 无法优化表的连接顺序。
外连接和内连接的本质区别就是:对于外连接的驱动表的记录来说,如果无法在被驱动表中找到匹配ON子句中的过滤条件的记录,那么该记录仍然会被加入到结果集中,对应的被驱动表 记录的各个字段使用NULL值填充;而内连接的驱动表的记录如果无法在被驱动表中找到匹配ON子句中的过滤条件的记录,那么该记录会被舍弃
凡是不符合WHERE子句中条件的记录都不会参与连接。只要我们在搜索条件中指定关于被驱动表相关列的值不为NULL,那么外连接中在被驱动表中找不到符合ON子 句条件的驱动表记录也就被排除出最后的结果集了,也就是说:在这种情况下:外连接和内连接也就没有什么区别了!
子查询
|
|
子查询查询方式
|
|
IN子查询优化
在MySQL5.5以及之前的版本没有引进semi-join和物化的方式优化子查询时,优化器都会把IN子查询转换为EXISTS子查询,所以当时好多声音都是建议大家把子查询转为连接,不过随着MySQL的发展,最近的版本中引入了非常多的子查询优化策略,大家可以稍微 放心的使用子查询了,内部的转换工作优化器会为大家自动实现。
|
|
- 不直接将不相关子查询的结果集当作外层查询的参数,而是将该结果集写入一个临时表里 (称为物化)
- 一般情况下子查询结果集不会大的离谱,所以会为它建立基于内存的使用Memory存储引擎的临时表,而且会为该表建立哈希索引。
- 如果子查询的结果集非常大,超过了系统变量
tmp_table_size
或者max_heap_table_size
,临时表会转而使用基于磁盘的存储引擎来保存结果集中的记录,索引类型也对应转变为B+树索引。
最后如果物化表没重复值甚至还会与物化表进行连接查询 SELECT s1.* FROM s1 INNER JOIN materialized_table ON key1 = m_val;
下面条件是会转半连接SEMI JOIN 的情况
对于s1表的某条记录来说,我们只关心在s2表中是否存在与之匹配的记录是否存在,而不关心具体有多少条记录与之匹配,最终的结果集中只保留s1表的记录。
- 该子查询必须是和IN语句组成的布尔表达式,并且在外层查询的WHERE或者ON子句中出现。
- 外层查询也可以有其他的搜索条件,只不过和IN子查询的搜索条件必须使用AND连接起来。
- 该子查询必须是一个单一的查询,不能是由若干查询由UNION连接起来的形式。
- 该子查询不能包含GROUP BY或者HAVING语句或者聚集函数