原来面试的时候,是作为面试题背的..
什么MySQL In 使用Exists方式,很慢...
面试官问怎么办..回答用内连接改写..
然后面试官露出满意笑容..
一直以来都是这个剧本..
直到昨天我才发现..这个剧本原来是错的.
实验数据
create table song(
?songid int
?);
?insert into song values(1),(2),(3);
?create table song_category_relation(
?Category varchar(10),
?songid int
?);
?insert into song_category_relation values
?('华语',1),
?('华语',2),
?('华语',3),
?('热门',3);
?song是歌曲表
song_category_relation是歌曲和分类的映射关系表.
一个歌曲可能有多个分类.
需求.
已知一个歌曲的ID,找到这个歌曲所属的所有分类,然后再找到所有分类下的所有歌曲.
使用In
?select * from song where songid in (
?select songid from song_category_relation where Category in
?(select Category from song_category_relation where songid=3)
?);

但是此时如果用内连接改写..
select * from song inner join? (
?select songid from song_category_relation where Category in
?(select Category from song_category_relation where songid=3)
?) a on (a.songid=song.songid);

可以看到,两种方式的结果并不相同..
从逻辑上看,In后面的子查询经过了去重.
原来是通过Exists实现的.MySQL 5.6之后,采用了Semi Join优化.