msyql join语句执行原理

首先,我建了一个表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.cnblogs.com/sjks/p/10853245.html

时间: 2024-10-07 16:53:34

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

sql语句的执行原理

SQL语句执行过程详解 2014-07-17 01:15:43 分类: Oracle SQL语句执行过程详解一条sql,plsql的执行到底是怎样执行的呢?一.SQL语句执行原理:第一步:客户端把语句发给服务器端执行当我们在客户端执行 select 语句时,客户端会把这条 SQL 语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle 客户端是不会做任何的操作,他的主要任务就是把客户端产生的一些 SQL 语句发送给服务器端.虽然在客户端也有一个数据库进程,但是,这个进程的作用跟

SQL语句执行过程详解

一.SQL语句执行原理: 第一步:客户端把语句发给服务器端执行 当我们在客户端执行select语句时, 客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle客户端是不会做任何的操作,它的主要任务就是把客户端产生的一些SQL语句发送给服务器端.虽然在客户端也有一个数据库进程,但是,这个进程的作用跟服务器上的进程作用不同.服务器上的数据库进程才会对SQL语句进行相关的处理.不过,有个问题需要说明,就是客户端的进程跟服务器的进程是一 一对应的.也就是说,在客户端

Join的实现原理及优化思路

前言 前面我们已经了解了MySQLQueryOptimizer的工作原理,学习了Query优化的基本原则和思路,理解了索引选择的技巧,这一节我们将围绕Query语句中使用非常频繁,且随时可能存在性能隐患的Join语句,继续我们的Query优化之旅. Join 的实现原理 在寻找Join语句的优化思路之前,我们首先要理解在MySQL中是如何来实现Join的,只要理解了实现原理之后,优化就比较简单了.下面我们先分析一下MySQL中Join的实现原理. 在MySQL中,只有一种Join算法,就是大名鼎

转 Join的实现原理及优化思路

前言 前面我们已经了解了MySQLQueryOptimizer的工作原理,学习了Query优化的基本原则和思路,理解了索引选择的技巧,这一节我们将围绕Query语句中使用非常频繁,且随时可能存在性能隐患的Join语句,继续我们的Query优化之旅. Join 的实现原理 在寻找Join语句的优化思路之前,我们首先要理解在MySQL中是如何来实现Join的,只要理解了实现原理之后,优化就比较简单了.下面我们先分析一下MySQL中Join的实现原理. 在MySQL中,只有一种Join算法,就是大名鼎

MySQL join的实现原理及优化思路

Join 的实现原理 在MySQL 中,只有一种Join 算法,也就是Nested Loop Join,没有其他很多数据库所提供的Hash Join,也没有Sort Merge Join.顾名思义,Nested Loop Join 实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果.如果还有第三个参与Join,则再通过前两个表的Join 结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复. 下面

DBA大牛告诉你,如何让MySQL语句执行加速?

一打开科技类论坛,最常看到的文章主题就是MySQL性能优化了,为什么要优化呢?因为:数据库出现瓶颈,系统的吞吐量出现访问速度慢随着应用程序的运行,数据库的中的数据会越来越多,处理时间变长数据读写速度缓慢就是咱们说的"性能问题",程序员一遇到它总是焦头烂额!今天我对MySQL优化总结了一些心得,希望在大家之后的工作中能有所有帮助!like 前导符优化like模糊查询形如'%AAA%'和'%AAA'将不会使用索引,但是业务上不可避免可能又需要使用到这种形式.通常的方法有两种:方案一:使用覆

python 3 mysql sql逻辑查询语句执行顺序

python 3 mysql sql逻辑查询语句执行顺序 一 .SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_table> ON <join_condition> WHERE <where_condition> GROUP BY <group_by_list> HAVING <havin

Python源码剖析笔记3-Python执行原理初探

Python源码剖析笔记3-Python执行原理初探 本文简书地址:http://www.jianshu.com/p/03af86845c95 之前写了几篇源码剖析笔记,然而慢慢觉得没有从一个宏观的角度理解python执行原理的话,从底向上分析未免太容易让人疑惑,不如先从宏观上对python执行原理有了一个基本了解,再慢慢探究细节,这样也许会好很多.这也是最近这么久没有更新了笔记了,一直在看源码剖析书籍和源码,希望能够从一个宏观层面理清python执行原理.人说读书从薄读厚,再从厚读薄方是理解了

C++ 构造函数执行原理

作者 : 卿笃军 构造函数 ,是一种特殊的方法 .主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 .特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载.(这句话来自百度百科) 由上面这句话,我们知道:构造函数,是用来给对象开辟空间并初始化对象的~~~~~ 那么,构造函数具体是如何执行的呢?下面附上一张图,图解构造函数执行过程: 第一步:构造函数接收到主函数传进来的参数,图中①. 第二步:根据