mysql leftjoin 大表在外_小表驱动大表

前言

在数据库查询中,经常用到表关联,听到最多的规则是 “小表驱动大表”。那么问题来了

  • 什么是小表驱动大表 ?

  • 为什么要用小表驱动大表 ?

  • 怎么区分那个是驱动表与被驱动表 ?

  • JOIN查询如何选择驱动表与被驱动表 ?

  • 索引应该建在驱动表还是被驱动表 ?

1.什么是小表驱动大表 ?

小表驱动大表指的是用小的数据集驱动大的数据集。

2.为什么要用小表驱动大表 ?

例如:现有两个表A与B ,表A有200条数据,表B有20万条数据 ;
按照循环的概念举个例子

  • 小表驱动大表 > A驱动表,B被驱动表

 for(200条){
for(20万条){
...
}
}
  • 大表驱动小表 > B驱动表,A被驱动表

 for(20万){
for(200条){
...
}
}

总结:

  • 如果小的循环在外层,对于表连接来说就只连接200次 ;

  • 如果大的循环在外层,则需要进行20万次表连接,从而浪费资源,增加消耗 ;

综上:
小表驱动大表的主要目的是通过减少表连接创建的次数,加快查询速度 。

3.怎么区分那个是驱动表与被驱动表 ?

通过EXPLAIN查看SQL语句的执行计划可以判断在谁是驱动表,EXPLAIN语句分析出来的第一行的表即是驱动表 ;

4.JOIN查询如何选择驱动表与被驱动表 ?

在JOIN查询中经常用到的 inner join、left join、right join
问题解答:
1.当使用left join时,左表是驱动表,右表是被驱动表 ;
2.当使用right join时,右表时驱动表,左表是驱动表 ;
3.当使用inner join时,mysql会选择数据量比较小的表作为驱动表,大表作为被驱动表 ;

测试结论:
测试环境配置:MYSQL 5.7
数据准备:
创建两张测试表 大表 user_big_info ,测试数据400万条, 小表user_small_info ,测试数据200万条 ;

CREATE TABLE `user_small_info` (  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',  `user_id` varchar(32) NOT NULL COMMENT '用户唯一标识',  `username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',  `password` varchar(255) NOT NULL DEFAULT '' COMMENT '密码',  `real_name` varchar(32) NOT NULL DEFAULT '' COMMENT '真实姓名',  `phone` varchar(32) NOT NULL DEFAULT '' COMMENT '手机号码',  `remarks` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态 1-启用 2-禁用 ',  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  PRIMARY KEY (`id`),  UNIQUE KEY `uniq_user_id` (`user_id`) USING BTREE,  KEY `idx_username` (`username`) USING BTREE) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='用户表';

LEFT JOIN 测试
小表驱动大表063ed0d5d078ea5cd4b77810ed8c27b7.png

执行时间:18.141s ,由于使用左连接以小表为主表所以,返回行数:200万
执行计划e176dc438b70fe7acd1cf082c3cf9154.png

大表驱动小表8435e6cf95b95329fbf2dd74847e1dab.png

执行时间:25.949s ,由于使用左连接以大表为主表所以,返回行数: 400万
执行计划739a7fd1dfdde1094cf49927199feb1d.png

结论:

  • 当使用left join时,左表是驱动表,右表是被驱动表 ; ;

  • 在执行效率上,小表驱动大表优于大表驱动小表 ;

  • 驱动表索引没有生效,被驱动表索引有效 ;

INNER JOIN 测试
小表驱动大表b6bd94051621d189171b3f8ff32e9de7.png

执行时间:18.660s ,等值连接返回行数:200万

执行计划99416ccac9f6fea5c7795d5e6ea33aa9.png

大表驱动小表22e1177470693d74d01423ca24d2329c.png

执行时间:19.060s ,等值连接返回行数:200万

执行计划dcb818d9c99c534e5c47e546c52860f3.png

结论:

  • 当使用inner join时,数据库会选择数据量比较小的表作为驱动表,大表作为被驱动表 ;

  • 在执行效率上,那个作为主表关系不大,执行效率差距不大 ;

  • 驱动表索引没有生效,被驱动表索引有效 ;

  • 17
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值