实为吾之愚见,望诸君酌之!闻过则喜,与君共勉

测试数据

CREATE TABLE `dept_emp` (

`emp_no` int(11) NOT NULL,

`dept_no` char(4) NOT NULL,

`from_date` date NOT NULL,

`to_date` date NOT NULL,

PRIMARY KEY (`emp_no`,`dept_no`),

KEY

`from_date` (`from_date`),

CONSTRAINT `dept_emp_ibfk_1` FOREIGN KEY (`emp_no`) REFERENCES

`employees` (`emp_no`) ON DELETE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=latin1

CREATE TABLE `departments` (

`dept_no` char(4) NOT NULL,

`dept_name` varchar(40) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=latin1

mysql> select count(1) from departments;

+----------+

| count(1) |

+----------+

|

9 |

+----------+

1 row in set (0.00 sec)

mysql> select count(1) from dept_emp;

+----------+

| count(1) |

+----------+

|

331603 |

+----------+

1 row in set (0.08 sec)

其中dept_emp有331603行记录,departments有9行数据

事例查询

select e.to_date,d.dept_name from dept_emp

e,departments d where e.dept_no=d.dept_no;

这是一个两表join的query,对应条件是where e.dept_no=d.dept_no,主要找出表dept_emp和departments中,满足dept_no相等的记录,然后展示出e.to_date,d.dept_name列其中dept_emp有331603行记录,departments有9行数据

执行计划对比

关闭block_nested_loop

打开block_nested_loop

打开batched_key_access

Nested-Loop事例

Nested-Loop Join

关闭设置optimizer_switch的block_nested_loop为off,然后查看查询的执行计划

从上图可知,执行计划对departments是全表扫描(9行数据),对dept_emp也是全表扫描(331570行数据),当使用Nested-Loop Join算法的时候,先逐行的读取departments表(此处是全表扫描,仅限于该sql),针对departments的每一行数据,都对表dept_emp的每一行记录进行匹配(此处是全表扫描,仅限于该sql)满足条件的行(where e.dept_no=d.dept_no),wiki的伪代码如下:

For each tuple r in R do

For each tuple s in S do

If r and s satisfy the join condition

Then output the tuple

过程概括如下图:

上图所示,departments的row1要和dept_emp每一行做条件匹配,查找符合条件的行,反复循环,直至departments的记录扫描完成(最后一条记录rown与dept_emp的每一行都进行了条件匹配)

Block_nested_loop

先打开设置optimizer_switch的block_nested_loop为on,然后查看查询的执行计划

从上图可知,执行计划对departments是全表扫描(9行数据),对dept_emp也是全表扫描(331570行数据),但是extra列多了一部分” Using join buffer (Block Nested Loop)”,当使用Block

Nested-Loop Join算法的时候,先逐行的读取departments表(此处是全表扫描,仅限于该sql),然后把读取的数据,存储到join buffer里(如果join buffer足够大,就可以一次全部存储departments所需要的join对象了,如果join buffer太小,一次只可以缓存departments的一部分join对象的话,就需要分多次进行缓存departments的join对象),针对join buffer中缓存的数据(注意之前的一次缓存以及多次缓存),批量(不需要与Nested-Loop Join一样,一条条的比较了,可以多条比较了)的对表dept_emp的每一行记录进行匹配(此处是全表扫描,仅限于该sql)满足条件的行(where e.dept_no=d.dept_no),伪代码可以写成(参考的wiki):

For each tuple r in R do

store used columns from R in join buffer

For each tuple s in S do

If r and s satisfy the join condition

Then output the tuple

过程概括如下图:

当为dept_emp表的列dept_no添加一个索引的时候(二级索引,已经有主键索引),再观察执行计划:

Join type从all变成了ref,可以理解为对dept_emp执行join的时候,使用索引进行匹配(对应之前的全表扫描),这里预估的行数是20723rows,比之前的331570rows少了很多(全表扫描),执行计划从全表扫描和ref(join type)中,选择了

ref,对比之前的block_nested_loop,过程变化如下:

由于dept_emp下的dept_no是二级索引,查询中又查询了e.to_date(单单从二级索引里获取不到数据),于是需要通过索引,查询表里面对应的e.to_date的值,这是如上图可知,访问时随机的(图例的表现方式是row1对应pk2,row2对应pk1等等),可能会产生随机io,如果不查询e.to_date,则不需要再去表里查询了,同时Extra会显示Using index,如下:

Batched_key_access

在Block_nested_loop最后部分,使用二级索引查询的时候,出现了一个现象:当获取的数据二级索引无法满足时,需要去查询原始的数据表来确定数据,查询数据是通过主键去查的,会出现不是按照主键顺序查的情况,如果有办法把这些无序的主键查询转换成有序的去查询表的数据(聚簇索引),会节省很多的时间,mysql提供了Batched_key_access算法来实现这个需求,复现如下:

对比之前的Block_nested_loop(有索引和没有索引两部分),上面加索引后,开启了mrr,batched_key_access,同时关闭了mrr_cost_based,这个时候Extra列出现了Using join buffer (Batched Key Access),使用Batched_key_access的过程如下:

上图看,join buffer会缓存departments相关的join列,Batched_key_access算法会使用dept_no二级索引去查找,由于是无序的,查找前把这些key(可以大概理解为主键信息+join buffer里行的标识信息)的信息反馈给mrr 去,mrr会按照主键(没有主键使用row id)排序,然后顺序的去dept_emp里去查找信息,并发信息再次反馈给Batched_key_access算法去和join buffer里的row进行比较

mysql的join算法_mysql的Join算法-阿里云开发者社区相关推荐

  1. mysql权限create细化_mysql权限精细化分配-阿里云开发者社区

    mysql中可以给你一个用户授予如select,insert,update,delete等其中的一个或者多个权限,主要使用grant命令,用法格式为: grant 权限 on 数据库对象 to 用户 ...

  2. mysql double 存储_关于MYSQL中FLOAT和DOUBLE类型的存储-阿里云开发者社区

    关于MYSQL中FLOAT和DOUBLE类型的存储 重庆八怪 2016-04-12 844浏览量 简介: 关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方 ...

  3. 阿里mysql数据库同步_如何对MySQL数据库中的数据进行实时同步-阿里云开发者社区...

    数据传输(Data Transmission) 支持以数据库为核心的结构化存储产品之间的数据传输. 它是一种集数据迁移.数据订阅及数据实时同步于一体的数据传输服务.数据传输致力于在公有云.混合云场景下 ...

  4. 阿里云mysql测试_MySQL主主测试-阿里云开发者社区

    1.在两台主机上同时安装mysql,具体安装步骤 https://www.jianshu.com/p/7145991c9533 2.两台机器上都建立用户,并赋予复制权限: master1: mysql ...

  5. 阿里 mysql中间件_MySQL中间件ProxySQL介绍 -阿里云开发者社区

    ProxySQL作为一款强大的中间件为MySQL的架构提供了有力的支持. 目前可以很好的支持 Master Slave MGR PXC等,并提供连接池.读写分离.日志记录等功能,当然还有很多其他实用功 ...

  6. 阿里云 mysql日志分析_mysql 慢日志分析-阿里云开发者社区

    启用 slow log 有两种启用方式: 1, 在my.cnf 里 通过 log-slow-queries[=file_name] 2, 在mysqld进程启动时,指定--log-slow-queri ...

  7. dbcp释放不了mysql链接_spring dbcp连接不释放-问答-阿里云开发者社区-阿里云

    问题描述 这个spring配置,在使用过程中,基本上没插入200条数据后,通过mysql或netstat就可看到数据库连接达到10个, 并且mysql里面全部都是sleep状态.连接并没有释放,在等几 ...

  8. 阿里 mysql cluster_MySQL Cluster集群安装及使用-阿里云开发者社区

    MySQL Cluster MySQL集群 Linux最新版本7.3.2 文件 大小 md5 mysqlcluster-7.3.2-linux-x32.tar.gz 431.0MB 03093541b ...

  9. mysql5.5索引如何定义_MySQL5.5索引数在InnoDB引擎内与索引数在mysql中定义的数量是不一致问题-阿里云开发者社区...

    在查看MySQL错误日志的时候发现这样的错误,如下: 160322 21:42:59 [ERROR] Table baby/baby_order contains 12 indexes inside ...

  10. mysql5.7 备份恢复_RDS for MySQL 5.7 备份恢复为本地实例-阿里云开发者社区

    RDS for MySQL 5.7 备份恢复为本地实例 近期同学咨询反馈 RDS for MySQL 5.7 备份恢复本地实例的问题比较多,提供一个恢复样例. 1. 本地环境 # 项目 说明 1 OS ...

最新文章

  1. 从《王者荣耀》谈游戏的帧同步
  2. 安装Discuz!论坛
  3. Multisim14.0 安装教程
  4. Python基础day05【函数(函数传参的两种形式、函数形参)、拆包、引用、可变与不可变类型、引用做函数参数注意点】
  5. JAVA 通过串口发送命令
  6. 详解OTT与IPTV的不同之处
  7. 风控必须了解的报表权限与角色控制
  8. 创业者在创业时经常会问到的一个问题
  9. IIS 7.0与ASP.NET
  10. listView的最简单的使用方法
  11. MAGIX Sound Forge Audio Studio v16.0.0.39 WiN 音频编辑软件
  12. 防爆和本安的概念理解
  13. Fiona简介及Shapefile数据读取
  14. 华为linux连蓝牙鼠标,huawei蓝牙鼠标怎么样? 华为蓝牙鼠标连接使用教程
  15. 内存条 udimm rdimm 等和 ECC 功能
  16. 【SAP】SAP SD,中英日专业名词对照表
  17. 当 CPU 摸鱼时,它到底在干什么?
  18. (纯小白)Python简单爬取图片
  19. 2020牛客暑期多校训练营(第八场)E.Enigmatic Partition(差分+隔项差分/dp+暴力)
  20. 思科模拟器:cisco路由器密码恢复(密码破解)

热门文章

  1. ZooKeeper实战(一):ZooKeeper原理,详细安装步骤,基本命令,节点间通信原理
  2. Redis实战(八):面试常问:击穿,穿透,雪崩,分布式锁,API(jedis,luttce,springboot:low/high level)
  3. 【Git】撤销已经git add的文件
  4. 山谷序列C语言,通达信 山谷独创 主升黑马主图源码
  5. 03.shard_allocation_和_cluster的routing设置
  6. Promise第一篇:基本使用方法和串联
  7. jQuery——给元素添加父级的方法
  8. 满分简便代码——L1-049 天梯赛座位分配 (20分)
  9. 进阶Linux大佬的奠基石
  10. html 日历系统 源码,calendar.html