MySQL中join语句怎么优化

目录
  • Simple Nested-Loop Join
  • Block Nested-Loop Join
  • Index Nested-Loop Join
  • 如何选择驱动表?

Simple Nested-Loop Join

我们来看一下当进行 join 操作时,mysql是如何工作的。常见的 join 方式有哪些?

如图,当我们进行连接操作时,左边的表是驱动表,右边的表是被驱动表

Simple Nested-Loop Join 这种连接操作是从驱动表中取出一条记录然后逐条匹配被驱动表的记录,如果条件匹配则将结果返回。然后接着取驱动表的下一条记录进行匹配,直到驱动表的数据全都匹配完毕

因为每次从驱动表取数据比较耗时,所以MySQL并没有采用这种算法来进行连接操作

Block Nested-Loop Join

既然每次从驱动表取数据比较耗时,那我们每次从驱动表取一批数据放到内存中,然后对这一批数据进行匹配操作。这批数据匹配完毕,再从驱动表中取一批数据放到内存中,直到驱动表的数据全都匹配完毕

批量取数据能减少很多IO操作,因此执行效率比较高,这种连接操作也被MySQL采用

对了,这块内存在MySQ中有一个专有的名词,叫做 join buffer,我们可以执行如下语句查看 join buffer 的大小

show variables like '%join_buffer%'

把我们之前用的 single_table 表搬出来,基于 single_table 表创建2个表,每个表插入1w条随机记录

CREATE TABLE single_table (
    id INT NOT NULL AUTO_INCREMENT,
    key1 VARCHAR(100),
    key2 INT,
    key3 VARCHAR(100),
    key_part1 VARCHAR(100),
    key_part2 VARCHAR(100),
    key_part3 VARCHAR(100),
    common_field VARCHAR(100),
    PRIMARY KEY (id),
    KEY idx_key1 (key1),
    UNIQUE KEY idx_key2 (key2),
    KEY idx_key3 (key3),
    KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;

create table t1 like single_table;
create table t2 like single_table;

如果直接使用 join 语句,MySQL优化器可能会选择表 t1 或者 t2 作为驱动表,这样会影响我们分析sql语句的过程,所以我们用 straight_join 让mysql使用固定的连接方式执行查询

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

运行时间为0.035s

执行计划如下

在Extra列中看到了 Using join buffer ,说明连接操作是基于 Block Nested-Loop Join 算法

Index Nested-Loop Join

了解了 Block Nested-Loop Join 算法之后,可以看到驱动表的每条记录会把被驱动表的所有记录都匹配一遍,非常耗时,能不能提高一下被驱动表匹配的效率呢?

估计这种算法你也想到了,就是给被驱动表连接的列加上索引,这样匹配的过程就非常快,如图所示

我们来看一下基于索引列进行连接执行查询有多快?

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

执行时间为0.001秒,可以看到比基于普通的列进行连接快了不止一个档次

执行计划如下

驱动表的记录并不是所有列都会被放到 join buffer,只有查询列表中的列和过滤条件中的列才会被放入 join buffer,因此我们不要把 * 作为查询列表,只需要把我们关心的列放到查询列表就好了,这样可以在 join buffer 中放置更多的记录

如何选择驱动表?

知道了 join 的具体实现,我们来聊一个常见的问题,即如何选择驱动表?

如果是 Block Nested-Loop Join 算法:

  • 当 join buffer 足够大时,谁做驱动表没有影响
  • 当 join buffer 不够大时,应该选择小表做驱动表(小表数据量少,放入 join buffer 的次数少,减少表的扫描次数)

如果是 Index Nested-Loop Join 算法

假设驱动表的行数是M,因此需要扫描驱动表M行

被驱动表的行数是N,每次在被驱动表查一行数据,要先搜索索引a,再搜索主键索引。每次搜索一颗树近似复杂度是以2为底N的对数,所以在被驱动表上查一行的时间复杂度是 2 ∗ l o g 2 N 2*log2^N 2∗log2N

驱动表的每一行数据都要到被驱动表上搜索一次,整个执行过程近似复杂度为 M + M ∗ 2 ∗ l o g 2 N M + M*2*log2^N M+M∗2∗log2N

显然M对扫描行数影响更大,因此应该让小表做驱动表。当然这个结论的前提是可以使用被驱动表的索引

总而言之,我们让小表做驱动表即可

当 join 语句执行的比较慢时,我们可以通过如下方法来进行优化

  • 进行连接操作时,能使用被驱动表的索引
  • 小表做驱动表
  • 增大 join buffer 的大小
  • 不要用 * 作为查询列表,只返回需要的列

到此这篇关于MySQL中join语句怎么优化的文章就介绍到这了,更多相关MySQL join语句优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL实战教程之Join语句执行流程

    目录 Join语句执行流程 一.Index Nested-Loop Join 二.Simple Nested-Loop Join 三.Block Nested-Loop Join 四.总结 Join语句执行流程 Hi,我是阿昌,今天学习记录的是关于Join语句执行流程的内容. 在实际生产中,关于 join 语句使用的问题,一般会集中在以下两类: 不让使用 join,使用 join 有什么问题呢? 如果有两个大小不同的表做 join,应该用哪个表做驱动表呢? 创建两个表 t1 和 t2 来说明.

  • MySQL中join语句的基本使用教程及其字段对性能的影响

    join语句的基本使用 SQL(MySQL) JOIN 用于根据两个或多个表中的字段之间的关系,从这些表中得到数据. JOIN 通常与 ON 关键字搭配使用,基本语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 通常称为左表,table2 称为右表.ON 关键字用于设定匹配条件,用于限定在结果集合中想要哪些行.如果需要指定其他条件,后面可以加上 WHERE 条件 或者 LIMIT 以限制记录返回数目等.

  • MySQL中union和join语句使用区别的辨析教程

    union和join是需要联合多张表时常见的关联词,具体概念我就不说了,想知道上网查就行,因为我也记不准确. 先说差别:union对两张表的操作是合并数据条数,等于是纵向的,要求是两张表字段必须是相同的(Schema of both sides of union should match.).也就是说如果A表中有三条数据,B表中有两条数据,那么A union B就会有五条数据.说明一下union 和union all的差别,对于union如果存在相同的数据记录会被合并,而union all不会合

  • mysql查询语句join、on、where的执行顺序

    目录 一.典型SELECT语句完整的执行顺序 二.from 三.on 四.on 条件与where 条件 1.使用位置 2.使用对象 3.选择与使用 五.join 流程 MySQL 的执行顺序 一.典型SELECT语句完整的执行顺序 1)from子句组装来自不同数据源的数据: 2)使用on进行join连接的数据筛选 3)where子句基于指定的条件对记录行进行筛选: 4)group by子句将数据划分为多个分组: 5)cube, rollup 6)使用聚集函数进行计算: 7)使用having子句筛

  • MySQL查询优化:连接查询排序limit(join、order by、limit语句)介绍

    不知道有没有人碰到过这样恶心的问题:两张表连接查询并limit,SQL效率很高,但是加上order by以后,语句的执行时间变的巨长,效率巨低. 情况是这么一个情况:现在有两张表,team表和people表,每个people属于一个team,people中有个字段team_id. 下面给出建表语句: 复制代码 代码如下: create table t_team ( id int primary key, tname varchar(100) ); create table t_people (

  • MySQL中(JOIN/ORDER BY)语句的查询过程及优化方法

    在MySQL查询语句过程和EXPLAIN语句基本概念及其优化中介绍了EXPLAIN语句,并举了一个慢查询例子: 可以看到上述的查询需要检查1万多记录,并且使用了临时表和filesort排序,这样的查询在用户数快速增长后将成为噩梦. 在优化这个语句之前,我们先了解下SQL查询的基本执行过程: 1.应用通过MySQL API把查询命令发送给MySQL服务器,然后被解析 2.检查权限.MySQL optimizer进行优化,经过解析和优化后的查询命令被编译为CPU可运行的二进制形式的查询计划(quer

  • 在MySQL中使用JOIN语句进行连接操作的详细教程

    到目前,我们已经学习了从一个表中获取数据.这是简单的需要,但在大多数现实MySQL的使用,经常需要将数据从多个表中的一个单一的查询. 可以使用多个表中的单一SQL查询.在MySQL中联接(join)行为是指两个或多个表到一个表中可以使用连接在SELECT,UPDATE和DELETE语句中加入MySQL表.我们将看到一个例子LEFT JOIN简单的MySQL连接. 在命令提示符使用联接: 假设我们两个表的教程tcount_tbl和tutorials_tbl的完整列表如下: 例子: 试试下面的例子:

  • MySQL中join语句怎么优化

    目录 Simple Nested-Loop Join Block Nested-Loop Join Index Nested-Loop Join 如何选择驱动表? Simple Nested-Loop Join 我们来看一下当进行 join 操作时,mysql是如何工作的.常见的 join 方式有哪些? 如图,当我们进行连接操作时,左边的表是驱动表,右边的表是被驱动表 Simple Nested-Loop Join 这种连接操作是从驱动表中取出一条记录然后逐条匹配被驱动表的记录,如果条件匹配则将

  • MySQL中EXPLAIN语句及用法实例

    目录 前言 EXPLAIN 语法如下: 1.获取表结构 2.获取执行计划信息 3.使用 EXPLAIN ANALYZE 获取信息 总结 前言 在MySQL中 DESCRIBE 和 EXPLAIN 语句是相同的意思.DESCRIBE 语句多用于获取表结构,而 EXPLAIN 语句用于获取查询执行计划(用于解释MySQL如何执行查询语句). 通过 EXPLAIN 语句可以帮助我们发现表格的哪些字段上需要建立索引,用于加速查询.也可以使用 EXPLAIN 检查优化器是否使用最优的顺序来连接表. EXP

  • MySQL中join查询的深入探究

    目录 前引 索引对 join 查询的影响 数据准备 有索引查询过程 无索引查询过程 了解 Block Nested-Loop Join Block Nested-Loop Join查询过程 Join_buffer 如何正确的写出 join 查询 驱动表的选择 什么是小表 结论: 前引 相信大家 MySQL 都用了很久了,各种 join 查询天天都在写,但是 join 查询到底是怎么查的,怎么写才是最正确的,今天我就和大家一起学习探讨一下 索引对 join 查询的影响 数据准备 假设有两张表 t1

  • MySQL中or语句用法示例

    1.mysql中or语法的使用,在mysql语法中or使用注意点. 项目遇到坑,遍历发放奖励数据查询错误!!! $sql = 'SELECT * FROM `vvt_spread_doubleegg_exchange_award` AS p WHERE p.`act_type` = 4 or p.`act_type` = 5 AND p.`user_id` = ' .$user_id ; sql中的or语法一般用于多个条件的查询,上面的语法查询的相当于:两个sql查询出来的数据集合. $sql

  • 细数MySQL中SQL语句的分类

    1:数据定义语言(DDL)   用于创建.修改.和删除数据库内的数据结构,如:1:创建和删除数据库(CREATE DATABASE || DROP  DATABASE):2:创建.修改.重命名.删除表(CREATE  TABLE || ALTER TABLE|| RENAME TABLE||DROP  TABLE):3:创建和删除索引(CREATEINDEX  || DROP INDEX)   2:数据查询语言(DQL)   从数据库中的一个或多个表中查询数据(SELECT)   3:数据操作语

  • Mysql中Join的使用实例详解

    在前几章节中,我们已经学会了如果在一张表中读取数据,这是相对简单的,但是在真正的应用中经常需要从多个数据表中读取数据. 本章节我们将向大家介绍如何使用MySQL 的 JOIN 在两个或多个表中查询数据. 你可以在SELECT, UPDATE 和 DELETE 语句中使用Mysql 的 join 来联合多表查询. 以下我们将演示MySQL LEFT JOIN 和 JOIN 的使用的不同之处. 在命令提示符中使用JOIN 我们在RUNOOB数据库中有两张表 tcount_tbl 和 runoob_t

  • MySQL group by语句如何优化

    在MySQL中,新建立一张表,该表有三个字段,分别是id,a,b,插入1000条每个字段都相等的记录,如下: mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(1

  • MySql中JOIN的用法示例详解

    目录 笛卡尔积:CROSS JOIN 内连接:INNER JOIN 左连接:LEFT JOIN 右连接:RIGHT JOIN 外连接:OUTER JOIN USING子句 自然连接:NATURE JOIN 上次面试被问到JOIN,自己都已经忘了课堂上讲的笛卡尔积那些就是JOIN,最近重新复习了一遍 JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接. 先创建两个表,下面用于示例 CREATE TABLE t_blog( id INT PRIM

  • MySql中sql语句执行过程详细讲解

    目录 前言: sql语句的执行过程: 查询缓存: 分析器: 优化器: 执行器: 总结 前言: 很多人都在使用mysql数据库,但是很少有人能够说出来整个sql语句的执行过程是怎样的,如果不了解执行过程的话,就很难进行sql语句的优化处理,也很难设计出来优良的数据库表结构.这篇文章主要是讲解一下sql语句的执行过程. sql语句的执行过程: 客户端.连接器.分析器.优化器.执行器.存储引擎几个阶段. 连接器的作用:管理链接.权限验证的处理. 分析器的作用:词法分析.语法分析. 优化器的作用:执行计

随机推荐