Sql中为什么要小表驱动大表,以及In以及exists的使用对比

一.分析

mysql的join实现原理是,以驱动表的数据为基础,“嵌套循环”去被驱动表匹配记录,

这里的小表驱动大表速度快的前提是:两个表上根据主/外键建立了索引,这样在根据某一条数据查找B+树时,速度就会大大提高,若没有建立索引,则两个表无论谁当作主表,查找数据的次数都是一样的

select * from a join b on a.bid =b.id

假设 a表10000数据,b表20数据

这里有2个过程,b 表数据最少,查询引擎优化选择b为驱动表,

  • 循环b表的20条数据,
  • 去a表的10000数据去匹配,这个匹配的过程是B+树的查找过程,比循环取数要快的多。
  1. 小表驱动的方式
for  20条数据
   匹配10000数据(根据on a.bid=b.id的连接条件,进行B+树查找)

查找次数 20+ log10000

2.如果使用大表驱动,则查找过程是这样的

for 10000条数据
    匹配20条数据(根据on a.bid=b.id的连接条件,进行B+树查找)

查找次数 10000+ log20

二.结论

可以看出来
小表驱动大表:20+ log10000
大表驱动小表:10000+ log20
显然小表驱动大表查询效率要高很多。

C.小表驱动大表的案例:

 

三.in和exists的对比:


下面关于大表和小表的讨论均为A是小表


a.小表放到in之后的效率优于放到in之前
:select name from B where id in(select id in A);
分析:

1>IN的语法理解:MySql 的执行顺序会先执行子查询,再执行主查询,然后获得我们要查询的数据。

2>上面的查询语句可以拆成 首先 select id in A; 其次 select name from B where B.id=A.id; 


b.exists
例:select name from A where exists (Select * from B where B.id=A.id);
分析:

1>将EXISTS 语法理解为:将主查询的数据放在子查询中做条件验证,根据结果TRUE 和 FALSE 来决定主查询中的数据是否需要保留,EXISTS 子查询只返回TRUE 或 FALSE .Exists就是将主查询出的每一条语句放到exists后的子查询中存在即保留。exists/no exists具体用法可看:https://blog.csdn.net/qq_39552268/article/details/111934416

2>先遍历小表A,取得A中每个值和B中的值进行比对,如果比对成功了返回true

 

总之,什么时候用In,什么时候用exists呢?

1>根据两个表的数据量判断:

我们使用IN 优于 EXISTS。当A表中数据多于 B表中的数据时(我们这里只是假设),这时我们使用EXISTS 优于 IN。因此是使用IN 还是使用EXISTS 就需要根据我们的需求决定了。但是如果两张表中的数据量差不多时那么是使用IN 还是使用 EXISTS 差别不大。

2>根据限制条件来判断:

虽然exists和in都有过滤功能,他俩最大的差别就是in引导的子句只能对一个字段进行限制,比如

但是如果我们想对多个字段进行限制,使用in就不合适了。具体可参考:https://blog.csdn.net/qq_39552268/article/details/111934416

 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
小表驱动大表是一种常见的SQL优化技巧,通过将大表的数据先过滤到小表,再进行连接操作,可以提高查询的效率。下面是一些常用的小表驱动大表SQL优化方法: 1. 子查询优化:将大表小表的关联字段作为子查询的条件进行过滤,将结果存储到临时表,然后再与大表进行连接操作。 示例: ``` SELECT * FROM big_table WHERE id IN (SELECT id FROM small_table) ``` 2. EXISTS子查询:使用EXISTS子查询来判断大表小表的关联字段是否存在匹配的记录,可以提前结束查询,避免全表扫描。 示例: ``` SELECT * FROM big_table b WHERE EXISTS (SELECT 1 FROM small_table s WHERE s.id = b.id) ``` 3. 内连接优化:将小表作为内连接的驱动表,这样可以让数据库优先处理小表,减少连接操作的数据量。 示例: ``` SELECT * FROM small_table s INNER JOIN big_table b ON s.id = b.id ``` 4. 利用临时表:将大表小表的关联字段作为索引创建临时表,在临时表上进行连接操作,可以减少连接操作的数据量。 示例: ``` CREATE TEMPORARY TABLE temp_table (INDEX (id)) SELECT id FROM small_table SELECT * FROM temp_table t INNER JOIN big_table b ON t.id = b.id ``` 需要根据具体的查询场景和数据特点选择合适的优化方法。同时,也要注意合理设计索引和数据模型,以及定期更新统计信息,这些对于小表驱动大表的优化也是很重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值