left join 临时表_不懂SQL优化?那你就OUT了——表连接的优化
上一遍我们讨论了where 子句的优化,这一遍我们来讨论一下表连接的优化
我们知道在数据库中表连接有两种方式:
1. 内连接(inner join)2. 外连接(左外连接(left join), 右外连接(right join),全外连接(full join-->mysql 不支持全外连接)
什么是表连接
表连接就是指将多个表联合在一起实现查询。
表连接的原理
表连接采用的是笛卡尔乘积,称之为横向连接.
笛卡尔乘积
笛卡尔乘积:是指将多张表的所有数据相连,最后连接的结果数为多张表数量的乘积。
例如:这里有一张学生信息表(3条数据) 和 一张班级表(4条数据)
表连接是采用笛卡尔乘积的原理,所以两张表相连的结果 应该为 3 * 4 等于 12 条数据,
表连接的语法:
select 列名列表 from 表1 (inner | left | right )join 表2 on 过滤条件 (inner|left|right)join 表3 on 过滤条件...
内连接和外连接的区别
内连接:
内连接被称为普通连接或者自然连接,内连接是从结果表中删除与其他被连接表中没有匹配行的所有行。
(注意:内连接可能会丢失信息)
如图:
左外连接:
左外连接的结果集包括 left outer join子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。
如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
注:
写在 左边的表 叫做 左表
写在 右边的表 叫做 右表
如图:
右外连接:
右外连接是左外连接的反向连接,将返回右表的所有行。
如果右表的某行在左表中没有匹配行,则将为左表返回空值.
如图:
全外连接:(mysql 不支持)
全外连接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表 列 包含空值。如果表之间有匹配行,则整个结果集包含基表的数据值。
如图:
MySQL的JOIN实现原理
在MySQL中,只有一种Join算法,就是大名鼎鼎的Nested Loop Join(嵌套循环连接),他没有其他很多数据库所提供的Hash Join,也没有Sort Merge Join。顾名思义,Nested Loop Join 实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join 结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复。
—— 摘自《MySQL 性能调优与架构设计》
如何优化表连接
1.经常在连接的列上,也是外键上创建索引,可以加快连接的速度;
例如:两张表,学生表和班级表
学生表中有 8388608 条数据
班级表中有 4条数据
未加索引时:
从结果看:
执行时间为: 7.43sec
对学生表进行了全表扫描(需要优化),扫描数据:8389023条
加上索引以后:
从结果看:
执行时间为: 4.56sec(效率提高了 2.87 s)
对学生表的也使用了索引,由全表扫描变成了ref,并且扫描数量为:41945, 查询效率明显提高了很多。
2. 驱动表的选择非常重要,驱动表的数据小可以显著降低扫描的行数,条件中尽量能够过滤一些行将驱动表变得小一点,用小表去驱动大表。
一般情况下参与联合查询的两张表都会一大一小,如果是内连接(join),在没有其他过滤条件的情况下MySQL会选择小表(数据少的表)作为驱动表, 如果是左外连接(left join)mysql会选择左边的表为驱动表,如果是右外连接(right join)则以右边的表作为驱动表。
如图1:(内连接)
从图1可以看出,mysql在做联合查询的时候,首先扫描的班级表,会自动选择小表(班级表(4条数据)为驱动表, 扫描班级表4条数据,然后在扫描学生表 41945 条数据。
如图2:(左外连接)
从图2可以看出,mysql在做左外连接查询的时候,会选择左边的表(学生表(8388608条数据)为驱动表。
首先扫描学生表 8389023条数据,再扫描班级班表 4 条数据。
如图3(右外连接)
从图3可以看出,mysql在做又外连接查询的时候,会选择右边的表(班级表)为驱动表。
首先扫描班级表 4 条数据,再扫描学生表 41945 条数据。
MySQL在执行join时会把join分为system/const/eq_ref/ref/range/index/ALL等好几类,连接的效率从前往后依次递减。
3.left join/right join和inner join时,尽量用inner join避免外联结和null,如果where条件中含有右表的非空条件(除开is null),则left join语句等同于join语句,可直接改写成join语句。
如图4:(left join)
从结果中看出,首先扫描的学生表,再是班级表,最后是教师表。
如果where条件中含有右表的非空条件,则left join语句等同于join语句,可直接改写成join语句。
如图5:
从上面的结果看,两句sql语句的执行计划是一样的。
4.在mysql的 left join 中条件放在 on 后面和在 where 后面是不同的
ON 条件(“A LEFT JOIN B ON 条件表达式”中的ON)用来决定如何从 B 表中检索数据行。
如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 NULL 的数据。
在连接匹配阶段 WHERE 子句的条件都不会被使用,仅在匹配阶段完成以后,WHERE 子句条件才会被使用。
ON/And: 使用And时,不论如何,左边主表都完全显示,辅表显示符合ON条件的那条数据,其他行辅表数据都为NULL
关键字 Where 是针对 所有表连接匹配数据以后,where条件将会从满足on 匹配条件的数据中再检索一次。
条件写在不同的位置,得到的结果可能会不同,这一点要注意。
例如:
条件写 on 后面 (由于数据较多,我只截取前10条数据)
显示左表所有的数据,在班级表中没有匹配的,都显示为null;
条件写 where 后面 (由于数据较多,我只截取前10条数据)
没有显示学生表中所有的数据,只是显示班级一的学生的信息,条件写在where后面,是在表连接匹配数据后,在进行了一次数据的检索。
On和Where都是作为条件约束来过滤数据,我们应该尽量在on过滤条件是尽可能多的匹配满足条件,然后减少where子句的检索。
left join 临时表_不懂SQL优化?那你就OUT了——表连接的优化相关推荐
- left join 临时表_图解SQL的JOIN
对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚.Codin ...
- sql 临时表_原创 | SQL优化之合理使用临时表
看海景大图的推文吗?将我们设为星标★即可~ SQL专栏 SQL基础知识汇总 SQL高级知识汇总 今天我们来讲讲临时表的优化技巧 临时表,顾名思义就只是临时使用的一张表,一种是本地临时表,只能在当前查询 ...
- sql join on和不用join区别_图解 SQL 各种 JOIN,太有用了!
点击上方蓝字关注小姐姐吧从业以来主要在做客户端,用到的数据库都是表结构比较简单的 SQLite,以我那还给老师一大半的 SQL 水平倒也能对付.现在偶尔需要到后台的 SQL Server 里追查一些数 ...
- SQL数据库语言基础之SqlServer多表连接查询与INNER JOIN内连接查询
文章目录 一.简单连接查询 二.多表连接查询 三.INNER JOIN 内连接查询 一.简单连接查询 1.直接连接:无连接规则连接两表,得到的是两个表的笛卡尔积. 连接后的行数=表1行数*表2行数 连 ...
- OceanBase SQL 执行计划解读(二)──── 表连接和子查询
前文<OceanBase SQL 执行计划解读(一)>介绍了单表查询中基本的执行计划解读,本文主要介绍简单的表连接和子查询相关的执行计划. 本文假设你对常用的表连接算法已有了解,包括:嵌套 ...
- mysql select符合查询_数据库select group by 和having语句 多表连接查询 复合查询
1.SELECT --group by 子句 group by子句按照指定的列column_name对表数据进行分组 group by 后面跟的列也叫分组特性列 使用group by后,能选择的列 ...
- sql left join用法_图解 SQL 中 JOIN 的各种用法
点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 作者:CodingStar cnblogs.com/BoyceYang/p/3145279 ...
- mysql 删除表记录的 存储过程命令_用SQL语句删除一个数据库的所有表和所有存储过程...
如果数据库里有很多表和存储过程,要用手动鼠标右键一个个删除是很麻烦的,用SQL语句来删除就方便很多了 删除所有的表: 如果由于外键约束删除table失败,则先删除所有约束: --/第1步******* ...
- fastreport.net 交叉表居中显示_浅析Sql中内连接、外连接、全连接、交叉连接的区别...
外连接(out join) 外连接分为外左连接(left outer join)和外右连接(right outer join) 注释:left outer join 与 left join 等价, 一 ...
最新文章
- python __setattr__ , __getattr__
- mse函数(均方误差函数)
- 怎么添加本地音乐_网易云音乐:60G免费云盘+隐藏彩蛋、技巧
- Objective-C 和 Swift 混编项目的小 Tips(一)
- 防止arp***方法
- mongodb 字段出现次数_MongoDB数据库
- mf模型 svd++_推荐系统算法(MF、FM、CF、SVD、LFM、SVD++、TItemCF、timeSVD++、模型融合)...
- Vue使用nextTick的原因和作用
- JAVA虚拟机创建对象
- C#之FileInfo的简单操作
- 苹果ipad邮箱找不到服务器,ipad怎么设置qq邮箱?苹果ipad qq邮箱设置教程
- Matlab设置黑色背景
- nyoj-234-吃土豆(动态规划)
- Python爬虫实战之五:requests-re多页爬取链家成都地区租房市场信息
- 将markdown 文件渲染 mhtml 的方式
- pytorch训练网络 程序未报错 但是训练不动
- 《自适应机器人交互白皮书》
- for语句和while循环二者无条件等价
- 多功能可视化搜索引擎3Dfind.it问世,开启零部件搜索新纪元
- netbox与ewebeditor兼容问题
热门文章
- jquery判断页面滚动条(scroll)是上滚还是下滚,且是否滚动到头部或者底部
- FCKeditor 2.6.4.1 初始化值不能显示中文问题
- Servlet3.0学习总结(三)——基于Servlet3.0的文件上传
- 如何捕获和分析 JavaScript Error
- [转]对于非数据库字段的查询过滤以及app_query.append的用法
- 常用Oracle系统表查询
- Linux Grep 命令说明
- 最优化算法python实现篇(3)——无约束一维极值(黄金分割法)
- linux 视频转gif,GitHub - alinuxsa/VideoToGIF: video to gif 视频转gif制作表情包插件(可以添加文字)...
- 自然语言处理库——TextBlob