mysql中semi-join的优化策略介绍

时间:2021-06-17 21:58:16

转自:http://blog.sina.com.cn/s/blog_4673e60301011qvx.html

1. 背景介绍

什么是semi-join?
所谓的semi-join是指semi-join子查询。 该子查询具有如下结构:
SELECT ... FROM outer_tables WHERE expr IN (SELECT ... FROM inner_tables ...) AND ...
即在where条件的“IN”中的那个子查询。
这种查询的特点是我们只关心outer_table中与semi-join相匹配的记录。

换句话说,最后的结果集是在outer_tables中的,而semi-join的作用只是对outer_tables中的记录进行筛选。这也是我们进行semi-join优化的基础,即我们只需要从semi-join中获取到最少量的足以对outer_tables记录进行筛选的信息就足够了。


Semi-join从一个表中返回的行与另一个表中数据行进行不完全联接查询(查找到匹配的数据行就返回,不再继续查找)。

Anti-semi-join从一个表中返回的行与另一个表中数据行进行不完全联接查询,然后返回不匹配的数据。

还可参考mysql 官网:http://dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html



所谓的最少量,体现到优化策略上就是如何去重
以如下语句为例:
select * from Country  where Country.Code in 
(select City.country from City where City.Population>1*1000*1000);
当中的semi-join: “
select City.country from City where City.Population>1*1000*1000
” 可能返回的结果集如下: China(Beijin), China(Shanghai), France(Paris)...
我们可以看到这里有2个China,分别来至2条城市记录Beijin和Shanghai, 但实际上我们只需要1个China就足够对outer_table  Country进行筛选了。所以我们需要去重。

2. Mysql支持的Semi-join策略
Mysql支持的semi-join策略主要有5个,它们分别为:
1. DuplicateWeedout: 使用临时表对semi-join产生的结果集去重。
mysql中semi-join的优化策略介绍
对应的匹配条件为:
mysql中semi-join的优化策略介绍

2. FirstMatch: 只选用内部表的第1条与外表匹配的记录。
mysql中semi-join的优化策略介绍
对应的匹配条件为:
mysql中semi-join的优化策略介绍


3. LooseScan: 把inner-table数据基于索引进行分组,取每组第一条数据进行匹配。
mysql中semi-join的优化策略介绍
对应的匹配条件为:
mysql中semi-join的优化策略介绍



4. Materializelookup: 将inner-table去重固化成临时表,遍历outer-table,然后在固化表上去寻找匹配。
对应的匹配条件:
mysql中semi-join的优化策略介绍


5. MaterializeScan: 将inner-table去重固化成临时表,遍历固化表,然后在outer-table上寻找匹配。
mysql中semi-join的优化策略介绍
对应的条件:
mysql中semi-join的优化策略介绍


参考:
1.mysql代码 (sql/sql_select.cc 的setup_semijoin_dups_elimination函数)
2.askmonty的knowledgebase