首先,我建了一个表t2,里面有1000条数据,有id,a,b三个字段,a字段加了索引

然后我又建立一个t1表,里面有100条数据,和t2表的前一百条数据一致,也是只有id,a,b三个字段,a字段加了索引

如下图

然后我们看这条语句,为了不影响效果,这里我用了STRAIGHT_JOIN ,也就是在这条语句里会把t1当做驱动表

select * from t1 STRAIGHT_JOIN t2 on t1.a=t2.a

那么这条语句的执行流程就是这样的

1.从t1表查询出一行数据R

2.查出R这行数据的a字段的值到t2表中去查询

3.查询符合条件的数据和R组成一行,组装成结果集返回到客户端

4.重复执行步骤1-3,知道查到t1表的末尾

总结:由于我们在t2表上的a字段建立了索引,所以在第二步的时候不需要做全表扫描,也就是说,我们执行这条语句的扫描行数是200行,

首先t1表是扫描了100行,当和t2表每行去匹配的时候又扫描了t2表100行,所以这条语句总共扫描行数是200行,这种算法的扫描行数还是可以的。

对应的流程图如下图所示,这种算法叫作"Index Nested-Loop Join",简称NLJ

select * from t1 STRAIGHT_JOIN t2 on t1.a=t2.b

然后我们在看这条语句,由于b字段没有索引,所以在执行这条语句的时候,去t2表匹配的时候就要进行全表扫描

所以这条语句执行后的扫描行数就是100*1000=10万行

这个算法也有个名字叫做

Simple Nested-Loop Join

但是mysql没有使用这个算法,而是使用了另一种算法,叫做

Block Nested-Loop Join,简称BNL

1.查询出t1的数据放入join_buffer中,由于这条语句是select *,因此是把整个表t1放入内存中

2.扫描表t2,将t2表的每一行数据和join_buffer中的数据进行匹配(全表扫描),符合条件的数据作为结果集的一部分返回

这里有个问题,如果join_buffer的大小不够存储t1表的数据怎么办呢?

其实也很简单,就是分成多部分查询放入join_buffer中

举个例子:

比如说join_buffer中只够存储50行数据,但是t1表有100行,那么就先查出t1表的50行数据放入join_buffer中,然后和t2表进行匹配

但是这样就带来了一个问题,也就是说我们要分两次放入join_buffer中,那么也就是说要对表t2进行两次全表扫描

这样扫描行数就是2200行了,不知道大家发现一个问题了没有,这个时候影响扫描行数的因素有哪些??

  第一个因素就是这个join_buffer_size这个参数,如果他足够大,那么我们就只需要扫描表t2一次了,所以说有的时候我们发现了这个问题,

可以通过调大join_buffer_size这个参数来提高性能,当然不是说这个参数越大越好,要根据各方面情况来衡量。

  第二个因素就是驱动表的大小,如果驱动表的数据小,那么要么不分段存入join_buffer中,那就只扫描了一次表t2,要么分段存入join_buffer中,这个时候,分段越少,那么扫描次数就越少

也就是说驱动表的数据越小越好

  所以我们要使用小表来做驱动表,小表不是说某个表的真实的数据,而是说通过当前执行的语句中条件以及查询的字段而算出来的数据

例如

          select t1.b,t2.* from t1 straight_join t2 on (t1.b=t2.b) where t2.id<=100;

    select t1.b,t2.* from t2 straight_join t1 on (t1.b=t2.b) where t2.id<=100;

    在这个例子中表t1只查询出b字段放入join_buffer中

    而表t2要把所有字段都放入join_buffer中,所以这个时候表t1是小表

这两种算法显然第一种算法也就是NLJ的性能要好,所以我们在写sql语句的时候要尽量让mysql使用这种算法

也就是要对连接的字段加上索引,如果该字段确实不适合加索引,没办法只能使用第二种算法,那么这个时候我们就要尽量使用小表来当做驱动表

了解更多:https://www.toutiao.com/c/user/83293539887/#mid=1633933053814798

  

msyql join语句执行原理的更多相关文章

  1. oracle-SQL语句执行原理和完整过程详解

    SQL语句执行过程详解 一条sql,plsql的执行到底是怎样执行的呢? 一.SQL语句执行原理 第一步:客户端吧语句发个服务端执行 当我们在客户端执行select语句时,客户端会把这条SQL语句发送 ...

  2. mysql join语句的执行流程是怎么样的

    mysql join语句的执行流程是怎么样的 join语句是使用十分频繁的sql语句,同样结果的join语句,写法不同会有非常大的性能差距. select * from t1 straight_joi ...

  3. SQL运行内幕:从执行原理看调优的本质

    相信大家看过无数的MySQL调优经验贴了,会告诉你各种调优手段,如: 避免 select *: join字段走索引: 慎用in和not in,用exists取代in: 避免在where子句中对字段进行 ...

  4. SQL语句执行过程详解

    一.SQL语句执行原理: 第一步:客户端把语句发给服务器端执行 当我们在客户端执行select语句时, 客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle客户 ...

  5. [转]MySQL查询语句执行过程详解

    Mysql查询语句执行原理 数据库查询语句如何执行?语法分析:首先进行语法分析,对使用sql表示的查询进行语法分析,生成查询语法分析树.语义检查:检查sql中所涉及的对象以及是否在数据库中存在,用户是 ...

  6. MySQL查询语句执行过程及性能优化(JOIN/ORDER BY)-图

    http://blog.csdn.net/iefreer/article/details/12622097 MySQL查询语句执行过程及性能优化-查询过程及优化方法(JOIN/ORDER BY) 标签 ...

  7. mysql系列九、mysql语句执行过程及运行原理(分组查询和关联查询原理)

    一.背景介绍 了解一个sql语句的执行过程,了解一部分都做了什么,更有利于对sql进行优化,因为你知道它的每一个连接.where.分组.子查询是怎么运行的,都干了什么,才会知道怎么写是不合理的. 大致 ...

  8. MySQL查询语句执行过程及性能优化-查询过程及优化方法(JOIN/ORDER BY)

    在上一篇文章MySQL查询语句执行过程及性能优化-基本概念和EXPLAIN语句简介中介绍了EXPLAIN语句,并举了一个慢查询例子:

  9. Oracle sql语句执行顺序

    sql语法的分析是从右到左 一.sql语句的执行步骤: 1)词法分析,词法分析阶段是编译过程的第一个阶段.这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构 ...

随机推荐

  1. 比Redux更容易上手的状态管理库

    前言 当项目越发复杂时,我们发现仅仅是提升状态已经无法适应如此复杂的状态管理了,程序状态变得比较难同步,操作,到处是回调,发布,订阅,这意味着我们需要更好的状态管理方式,于是就引入了状态管理库,如Re ...

  2. IE9的兼容性

    /* 解决IE9表格错位 */ .el-table--border th:last-of-type.gutter { display: table-cell !important; width: 50 ...

  3. 线程屏障CyclicBarrier实现原理

    生产环境中,存在需要等待多个线程都达到某种状态后,才继续运行的情景.并发工具CyclicBarrier就能够完成这种功能.本篇从源码方面,简要分析CyclicBarrier的实现原理. 使用示例 pu ...

  4. kali优化配置(1)

    前言 无论是工具还是物理机.虚拟机,我都遇到过惨绝人寰的配置错误.为了有效避免这些烦恼困住我,写一个排错文档之外,我还应当谨慎小心,从每一次配置走起..我的kali昨日的MySQL无法登陆,也没办法联 ...

  5. 动态新增删除tbody表格行与ajax请求完成后刷新父窗口问题

    获取tbody内的一行数据,包括hidden类型的数据$("#tbody_id").find("tr").each(function(){ var tdArr ...

  6. 理解Promise (2)

    一进来 我们开始执行 executor函数 传递两个参数 再调用 then 方法 ,then 方法里面有 OnResolve方法,OnReject 方法  在then 方法中,我们一开始的状态是pen ...

  7. 重启uwsgi

    sudo pkill -f uwsgi -9 uwsgi --ini mysite.uwsgi.ini

  8. Django的下载和基本指令

    1.下载Django pip3  install  django     #不写版本号的话,默认使下载最新版的django pip3  install   django == 2.1.2    #指定 ...

  9. dubbo、web应用 项目结构以及发布目录结构

    一.dubbo服务项目结构及发布结构 dubbo 服务项目结构 xxxxx-api 接口类和一些DTO 用于供其他项目依赖 需要提供dubbo服务的接口命名 以Facade结尾 (xxxxxFacad ...

  10. 定时任务crond

    在服务器上使用crond完成定时操作很方便, 下面简单记录一下. 常用的命令主要有以下三个: (1)编辑定时任务 crontab -e (2)   查看定时任务 crontab -l (3)  删除定 ...