赞
踩
写这个文章的起因是,因为面试的时候又面试官问我,a left join b和b right join a,有什么区别,我说没什么区别,查询结果一样,性能也一样,那个面试官便说,小表和大表的前后顺序对性能是有影响的,他说sql语句从左往右执行,如果左边是大表,会先扫描左边的表的数据,然后再扫描右边表的数据,真是误人子弟啊!下面用实践来打他脸!
我会有SqlServer和MySql分别做实践,因为这两个数据库在Sql执行解析的机制还是有很大不同的。
SqlServer:
tEBay_Trade=》数据量500W tPublic_Shop=>数据量30
- -----如果where条件命中索引 且只有一个索引
- --关于join 不管是大表在前还是小表在前,查询顺序总是以where索引所在表为第一扫描的表
- select * from tPublic_Shop s
- join tEBay_Trade t on s.id=t.ShopID
- where s.Id>10
- select * from tPublic_Shop s
- join tEBay_Trade t on s.id=t.ShopID
- where t.CreateDate>'2021-01-01'
--对于left join和right join 总是会以where条件索引所在的表为第一扫描表
- select * from tEBay_Trade t
- left join tPublic_Shop s on s.id=t.ShopID
- where t.CreateDate>'2021-01-01'
- select * from tPublic_Shop s
- left join tEBay_Trade t on s.id=t.ShopID
- where t.Id>10
- select * from tPublic_Shop s
- right join tEBay_Trade t on s.id=t.ShopID
- where t.CreateDate>'2021-01-01'
- -----如果where条件命中索引 且有多个索引
- --关于join 不管大表在前还是小表在后,如果有多个where条件命中索引,那么会以索引对应的最大的那个表为第一扫描表
- select * from tPublic_Shop s
- join tEBay_Trade t on s.id=t.ShopID
- where s.Id>10 and t.CreateDate>'2021-01-01'
- select * from tEBay_Trade t
- join tPublic_Shop s on s.id=t.ShopID
- where t.CreateDate>'2021-01-01' and s.Id>10
- -----如果没有索引或where条件未命中索引
- --join 如果没有索引或where条件未命中索引,系统会自动选择小表作为第一扫描表
- select * from tPublic_Shop s
- join tEBay_Trade t on s.id=t.ShopID
- select * from tEBay_Trade t
- join tPublic_Shop s on s.id=t.ShopID
--left join和right join 如果没有索引或where条件未命中索引,系统会自动选择小表作为第一扫描表
- select * from tEBay_Trade t
- left join tPublic_Shop s on s.id=t.ShopID
- select * from tPublic_Shop s
- left join tEBay_Trade t on s.id=t.ShopID
- select * from tPublic_Shop s
- right join tEBay_Trade t on s.id=t.ShopID
MySql这货就很不一样了,正规的跟野生的差别很明显:
tuser数据量:33954 torder数据量:4612
#关于join 不管索引是不是加在主表上,总是先扫描最小的表
- select * from tuser u
- join torder t on u.id=t.uid
- where u.id>500
- select * from tuser u
- join torder t on u.id=t.uid
- where t.createtime>='2021-07-01'
- select * from torder t
- join tuser u on u.id=t.uid
- where u.id>500
#不管是left join还是right join,如果没有条件命中索引,都是以主表为第一扫描的表
- select * from torder t
- left join tuser u on u.id=t.uid
- select * from tuser u
- right join torder t on u.id=t.uid
- select * from tuser u
- left join torder t on u.id=t.uid
#不管是left join还是right left,如果where条件命中索引,会以这个索引对应的表为第一扫描的表
- select * from torder t
- right join tuser u on u.id=t.uid
- where t.createtime>='2021-07-01'
- select * from torder t
- right join tuser u on u.id=t.uid
- where u.id>500
- select * from tuser u
- left join torder t on u.id=t.uid
- where t.createtime>='2021-07-01'
- select * from tuser u
- left join torder t on u.id=t.uid
- where u.id>500
总结:
关于SqlServer:
1、对于join,left join,right join,不管是大表在前还是小表在前,如果where条件命中索引,总会以where条件索引所在表为第一扫描的表
2、对于join,left join,right join,不管是大表在前还是小表在前,如果where条件命中索引,而且是多个索引,那么会以索引对应的最大的那个表为扫描的第一个表
3、对于join,left join,right join,不管是大表在前还是小表在前,如果where条件没有命中索引,系统会自动选择小表作为第一扫描表
关于MySql:
1、对于join,不管是大表在前还是小表在前,如果where条件命中索引,总是先扫描小表,而不是索引所在的表
2、对于left join和right join,不管是大表在前还是小表在前,如果where条件命中索引,会以索引对应的这个表为第一扫描的表
3、对于left join和right join,不管是大表在前还是小表在前,如果没有条件命中索引,都是以主表为第一扫描的表
所以:表的执行顺序是不以人的主管意志为转移的,如果自己不清楚,请不要随便讲出来。实践是检验真理的唯一标准
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。