小表驱动大表

1. 什么是驱动表和被驱动表

  • 驱动表是表连接中的基础表,也就是通过驱动表的全表数据集作为循环基础数据,然后将这个全表数据集里的一条一条的数据作为过滤条件到被驱动表中查询数据,最后合并。

2. 如何区分驱动表和被驱动表

  • 左连接中,左表是驱动表
  • 右连接中,右表是驱动表
  • 内连接中,mysql会自动选择数据量较小的表作为驱动表。

3. 什么是小表驱动大表

  • 将小表作为驱动表,大表作为被驱动表
  • 对于驱动表来说,需要全表扫描,所以建不建索引都无法优化查询速度
  • 对于被驱动表来说,可以将与驱动表连接的字段建立索引,能够优化查询速度。
  • 小表驱动大表是建议,而不是强制

4. 为什么要小表驱动大表

  • 假设索引是b+树,在索引上等值查询的时间复杂度为logN,小表为200条数据,大表为20000条数据
  • 因为驱动表不走索引,需要全表扫描而被驱动表可以建立索引加速查找
  • 若小表驱动大表,则时间复杂度为 200*log20000
  • 若大表驱动小表,则时间复杂度为 20000*log200
  • 所以看时间复杂度就自然清楚了。

5. 怎么理解连接查询

SELECT 
  * 
FROM
  students 
LEFT JOIN courses 
ON students.`cid` = courses.`id` ;

对于上面的查询,用java代码写就是这样

for(Student student:students){
    for(Course course:courses){
        if(course.id==student.cid){
            保留这条记录;
        }
    }
}
Map<Id,Course> courses= TreeMap<>()

for(Student student:students){
    if (courses.Contains(student.cid)){      // 速度差距在这儿。
        保留这条记录;
    }
}
  • 外层循环为students表,为驱动表,需要全表扫描,没法优化
  • 内存循环为courses表,为被驱动表,上面java代码中虽然是全表扫描,但是我们可以给course的id字段建立索引,然后通过索引查询优化,从而摆脱了全表扫描。

6. exists与in

        语句1

select * from A where id in (select id from B);
for select id from B     // B是驱动表
    for select * from A where A.id=B.id

      语句2

select * from A where exists (select 1 from B where B.id=A.id);
for select * from A        // A是驱动表
    for select * from B where B.id=A.id
  • 上述两个查询的查询结果是一样的,其实这两个查询可以写成连接查询的形式
  • 它们也是满足驱动表和被驱动表。
  • 如何区分谁是驱动表和谁是被驱动表,类比java的循环
  • 万变不离其宗,小表作为驱动表,大表上连接字段建立索引
  • 当然这些优化是理论上的,实际情况还要考虑多种因素。

  • 16
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值