MySQL深入——24

Join语句到底可不可用

join语句用于两个或多个表当中检索数据。

INNER JOIN或者JOIN 当两个表当中有匹配的值时,返回行

LEFT JOIN或者LEFT OUTER JOIN 返回所有左边的行,即使右表当中没有相匹配的行

RIGHT JOIN或者RIGHT OUTER JOIN 返回所有右边的行,即使左表当中没有相匹配的行

FULL JOIN或FULL OUTER JOIN 左表或右表有匹配的行时,返回行。

一般在日常生活当中,Join语句通常集中于下面这几个问题:1.DBA(DataBase Administer数据库管理员)不让使用join,使用join有什么问题?2.若有两个大小不同的表,选择哪个表作为驱动?

join语句的执行流程

创建两个表t1,t2,都有主键索引id和索引a,给t1插入100行数据,给t2插入1000条数据。

若是直接使用join语句,MySQL的优化器可能会选择t1或t2作为驱动表,为了方便分析,便限定出驱动表是什么。

select * from t1 straight_join t2 on(t1.a=t2.a)

使用straight_join让MySQL使用固定的方式执行查询,t1作为驱动表,t2作为被驱动表。

通过查看explain语句,知道了执行流程为:

1.从表t1中读取一行数据R

2.从数据页R当中取出字段到表t2中去查找满足的行,当满足的时候作为结果集的一部分返回

4.在t1中再读取一行进行对比。

5.直到t1被取完。

这个流程当中,对t1进行全表扫描,对于每一个行R,根据a索引去t2查找,走的是树查找过程,t1是全表遍历,总计扫描200行。这个算法称之为:Index Nested-Loop Join简称为NLJ算法。

那么假设不使用join,使用单表查询来做,首先得select * from t1 取出t1所有的值,共计100行。然后取出a的值进入t2进行遍历查询,返回结果构成一个结果集。我们可以看到不仅多了100多次交互,而且我们还得自己拼接结果集,所以使用join更好。

那么该如何选择驱动表呢?

通过分析得知,join语句执行过程中,驱动表走全表查询,被驱动表走树查询,可知驱动表越小越好。但是前提是我们可以使用被驱动表的索引下,若果被驱动表不使用索引会是什么情况。

将select语句改为select * from t1 straight_join t2 on(t1.a=t2.b)

b上无索引,所以每次匹配都要做一个全表扫描,这样子看上去十分繁重,所以InnoDB使用了一个Block Nested-Loop Join算法简称BNL算法,实现如下

因为select * 所以我们将t1全表放入到线程内存Join_buffer当中,扫描t2,将t2的每一行与Join_buffe当中的值作比较,由于Join_Buffer是无序的,所以对于t2的每一行,都要走一遍全表判断,故在内存做判断数为10万次。

因为是在内存当中操作,所以会更快。

而且这里是无所谓选什么表作为驱动表的,因为扫描的行数始终为一个表的行数乘上另外一个表的行数。

这里其实还存在着一个问题,要是表的数据过大,join_buffer无法放下一整个表该如何呢?

join_buffer的大小由join_buffer_size决定,默认为256k

处理方法其实很简单,就是分段放,假设join_buffer只能容纳下t1的一半,那么我们先放一半进去,然后扫描t2,将t2当中每一行取出来与t1在join_buffer当中的数据作比较,满足Join条件的返回结果集,最后判断结束后,清空join_buffer,将剩下的join_buffer放入继续判断。

这种情况下的驱动表选择是有说法的,驱动表的行数为n,被驱动表为m,n改为x*n(x*n是能放入join_buffer的大小)

1.扫描:n+x*n*m

2.内存判断:n*m次

我们可以看到x是越小越好的,join_buffer的大小固定,表越小x越小,所以选择小表作为驱动表。

那么什么是小表,定义是什么呢?

可以让两个表都不用索引,按照自己的条件过滤,运行完成之后计算join的各个字段数据量,数据量少的即为小表作为驱动表。

相关推荐
PcVue China2 小时前
PcVue + SQL Grid : 释放数据的无限潜力
大数据·服务器·数据库·sql·科技·安全·oracle
魔道不误砍柴功4 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
锐策4 小时前
〔 MySQL 〕数据库基础
数据库·mysql
远歌已逝5 小时前
管理Oracle实例(二)
数据库·oracle
日月星宿~5 小时前
【MySQL】summary
数据库·mysql
爱吃土豆的程序员5 小时前
在oracle官网下载资源显示400 Bad Request Request Header Or Cookie Too Large 解决办法
java·数据库·oracle·cookie
睿思达DBA_WGX5 小时前
Oracle 11g rac 集群节点的修复过程
数据库·oracle
尘浮生5 小时前
Java项目实战II基于微信小程序的移动学习平台的设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·学习·微信小程序·小程序
希忘auto6 小时前
详解MySQL安装
java·mysql
运维佬6 小时前
在 MySQL 8.0 中,SSL 解密失败,在使用 SSL 加密连接时出现了问题
mysql·adb·ssl