mysql join图解_MySQL中Join算法实现原理分析[多图]

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

还是通过示例和图解来说明吧,后面将通过我个人数据库测试环境中的一个 example(自行设计,非MySQL 自己提供) 数据库中的三个表的 Join 查询来执行

示例。

留心

:由于这里有些内容须要

在MySQL 5.1.18之后的版本中才会体现出来,所以本测试的MySQL 版本为5.1.26

表结构:

1 sky@localhost : example 11:09:32> show create table user_group\G

2

3 *************************** 1. row ***************************

4

5 table: user_group

6

7 Create table: CREATE table `user_group` (

8

9 `user_id` int(11) NOT NULL,

10

11 `group_id` int(11) NOT NULL,

12

13 `user_type` int(11) NOT NULL,

14

15 `gmt_create` datetime NOT NULL,

16

17 `gmt_modified` datetime NOT NULL,

18

19 `status` varchar(16) NOT NULL,

20

21 KEY `idx_user_group_uid` (`user_id`)

22

23 ) ENGINE=MyISAM DEFAULT CHARSET=utf8

24

25 1 row in set (0.00 sec)

26

27 sky@localhost : example 11:10:32> show create table group_message\G

28

29 *************************** 1. row ***************************

30

31 table: group_message

32

33 Create table: CREATE table `group_message` (

34

35 `id` int(11) NOT NULL AUTO_INCREMENT,

36

37 `gmt_create` datetime NOT NULL,

38

39 `gmt_modified` datetime NOT NULL,

40

41 `group_id` int(11) NOT NULL,

42

43 `user_id` int(11) NOT NULL,

44

45 `author` varchar(32) NOT NULL,

46

47 `subject` varchar(128) NOT NULL,

48

49 PRIMARY KEY (`id`),

50

51 KEY `idx_group_message_author_subject` (`author`,`subject`(16)),

52

53 KEY `idx_group_message_author` (`author`),

54

55 KEY `idx_group_message_gid_uid` (`group_id`,`user_id`)

56

57 ) ENGINE=MyISAM AUTO_INCREMENT=97 DEFAULT CHARSET=utf8

58

59 1 row in set (0.00 sec)

60

61 sky@localhost : example 11:10:43> show create table group_message_content\G

62

63 *************************** 1. row ***************************

64

65 table: group_message_content

66

67 Create table: CREATE table `group_message_content` (

68

69 `group_msg_id` int(11) NOT NULL,

70

71 `content` text NOT NULL,

72

73 KEY `group_message_content_msg_id` (`group_msg_id`)

74

75 ) ENGINE=MyISAM DEFAULT CHARSET=utf8

76

77 1 row in set (0.00 sec)运用

Query如下:

1 select m.subject msg_subject, c.content msg_content

2

3 from user_group g,group_message m,group_message_content c

4

5 where g.user_id = 1

6

7 and m.group_id = g.group_id

8

9 and c.group_msg_id = m.id

看看我们的 Query 的执行计划:

1 sky@localhost : example 11:17:04> exp

lain select m.subject msg_subject, c.content msg_content

2

3 -> from user_group g,group_message m,group_message_content c

4

5 -> where g.user_id = 1

6

7 -> and m.group_id = g.group_id

8

9 -> and c.group_msg_id = m.id\G

10

11 *************************** 1. row ***************************

12

13 id: 1

14

15 select_type: SIMPLE

16

17 table: g

18

19 type: ref

20

21 possible_keys: user_group_gid_ind,user_group_uid_ind,user_group_gid_uid_ind

22

23 key: user_group_uid_ind

24

25 key_len: 4

26

27 ref: const

28

29 rows: 2

30

31 Extra:

32

33 *************************** 2. row ***************************

34

35 id: 1

36

37 select_type: SIMPLE

38

39 table: m

40

41 type: ref

42

43 possible_keys: PRIMARY,idx_group_message_gid_uid

44

45 key: idx_group_message_gid_uid

46

47 key_len: 4

48

49 ref: example.g.group_id

50

51 rows: 3

52

53 Extra:

54

55 *************************** 3. row ***************************

56

57 id: 1

58

59 select_type: SIMPLE

60

61 table: c

62

63 type: ref

64

65 possible_keys: idx_group_message_content_msg_id

66

67 key: idx_group_message_content_msg_id

68

69 key_len: 4

70

71 ref: example.m.id

72

73 rows: 2

74

75 Extra:

我们可以看出,MySQL Query Optimizer 选择了 user_group 作为驱动表,首先运用

我们传入的条件 user_id 通过 该表上面的索引 user_group_uid_ind 来执行

const 条件的索引 ref 查找,然后以 user_group 表中过滤出来的结果集的 group_id 字段作为查询条件,对 group_message 循环查询,然后再通过 user_group 和 group_message 两个表的结果集中的 group_message 的 id 作为条件 与 group_message_content 的 group_msg_id 比较执行

循环查询,才得到最终的结果。没啥特别的,后一个引用前一个的结果集作为条件,实现流程

可以通过下图表示:

20094236525622529.jpg

下面的我们调整一下 group_message_content 去掉上面的 idx_group_message_content_msg_id 这个索引,然后再看看会是什么效果:

1 sky@localhost : example 11:25:36> drop index idx_group_message_content_msg_id on group_message_content;

2

3 Query OK, 96 rows affected (0.11 sec)

4

5 sky@localhost : example 10:21:06> exp

lain

6

7 -> select m.subject msg_subject, c.content msg_content

8

9 -> from user_group g,group_message m,group_message_content c

10

11 -> where g.user_id = 1

12

13 -> and m.group_id = g.group_id

14

15 -> and c.group_msg_id = m.id\G

16

17 *************************** 1. row ***************************

18

19 id: 1

20

21 select_type: SIMPLE

22

23 table: g

24

25 type: ref

26

27 possible_keys: idx_user_group_uid

28

29 key: idx_user_group_uid

30

31 key_len: 4

32

33 ref: const

34

35 rows: 2

36

37 Extra:

38

39 *************************** 2. row ***************************

40

41 id: 1

42

43 select_type: SIMPLE

44

45 table: m

46

47 type: ref

48

49 possible_keys: PRIMARY,idx_group_message_gid_uid

50

51 key: idx_group_message_gid_uid

52

53 key_len: 4

54

55 ref: example.g.group_id

56

57 rows: 3

58

59 Extra:

60

61 *************************** 3. row ***************************

62

63 id: 1

64

65 select_type: SIMPLE

66

67 table: c

68

69 type: ALL

70

71 possible_keys: NULL

72

73 key: NULL

74

75 key_len: NULL

76

77 ref: NULL

78

79 rows: 96

80

81 Extra: Using where; Using join buffer

我们看到不仅仅 group_message_content 表的访问从 ref 变成了 ALL,此外,在最后一行的 Extra信息从没有任何内容变成为 Using where; Using join buffer,也就是说,对于从 ref 变成 ALL 很容易理解,没有可以运用

的索引的索引了嘛,当然得执行

全表扫描了,Using where 也是因为变成全表扫描之后,我们须要

取得的 content 字段只能通过对表中的数据执行

where 过滤才能取得,但是后面出现的 Using join buffer 是一个啥呢?

我们知道,MySQL 中有一个供我们配置

的参数 join_buffer_size ,这里实际上就是运用

到了通过该参数所配置

的 Buffer 区域。那为啥之前的执行计划中没有用到呢?

实际上,Join Buffer 只有当我们的 Join 类型为 ALL(如示例中),index,rang 或者是 index_merge 的时候 才能够运用

,所以,在我们去掉 group_message_content 表的 group_msg_id 字段的索引之前,由于 Join 是 ref 类型的,所以我们的执行计划中并没有看到有运用

Join Buffer。

当我们运用

了 Join Buffer 之后,我们可以通过下面的这张图片来表示 Join 完成流程

20094236525683164.jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/533645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql多线程使用一个链接_探索多线程使用同一个数据库connection的后果

在项目中看到有用到数据库的连接池,心里就思考着为什么需要数据库连接池,只用一个连接会造成什么影响?(只用一个connection)?1 猜想:jdbc的事务是基于connection的,如果多线程共用一个connection,会造成多线程之间的事务相互干…

vs中四点画矩形的算法_中考热点,初高中衔接之倒角利器四点共圆

初中数学课程标准修改后,教材中四点共圆知识已经删除掉了,但这样一件强悍且使用简单的武器,我们还是有必要去了解的,近年来对于压轴题以几何为核心的考区来说,有时用到解题更为简洁方便,由此应该理解掌握。…

phpnow mysql字符集_使用PHPnow搭建本地PHP环境+创建MySQL数据库

要想学习WordPress建站,在本地搭建PHP环境是十分必要的,在以后的建站日子里,你可以使用这个环境来进行wordpress的程序学习、调试等工作,等你熟悉了wordpress以后,再购买域名和空间,真正开始你的建站之旅。…

wps如何保存最终状态_如何使得打开word文件显示最终的修改状态

展开全部 在日常工作中,经常为了保护文档而将其设置成最e68a84e8a2ad3231313335323631343130323136353331333363376366终状态,设置文档为最终状态,则是表示已完成这篇文档的编辑,这是文档的最终版本。如果文档被标记为最终状态,则状态属性将设置为“最终状态”,并且将禁用…

python整数反转_敲代码学Python:力扣简单算法之整数反转

学习重点:整数逆序算法力扣(LeetCode)原题​leetcode-cn.com 功能:整数反转 来源:https://leetcode-cn.com/explore/featured/card/top-interview-questions-easy/5/strings/33/ 重点:整数逆序算法 作者&am…

前端累加nan怎么解决_前端面试,你有必要知道的一些JavaScript 面试题(上)

1.使用 typeof bar “object” 判断 bar 是不是一个对象有神马潜在的弊端?如何避免这种弊端?使用 typeof 的弊端是显而易见的(这种弊端同使用 instanceof):let obj {};let arr [];console.log(typeof obj object); //trueconsole.log(typ…

tidb 配置mysql数据源_安装tidb数据库

1.下载压缩包安装tar包路径命令:wget http://download.pingcap.org/tidb-latest-linux-amd64.tar.gz命令:wget http://download.pingcap.org/tidb-latest-linux-amd64.sha2562.检查文件完整性命令:sha256sum -c tidb-latest-linux-amd64.sha2…

linuxos或sv独立客户端不支持应用程序打开方式_搞不明白为什么大家都在学习 k8s

作者 | 小明菜市场来源 | 小明菜市场(ID:fileGeek)头图 | CSDN 下载自东方IC前言都2020年了,你还不知道kubernetes就真的真的真的out啦。(贩卖焦虑体) 什么是k8s,k8s这个词来自于希腊语,有主管,舵手,船长的…

react 图片放在src里面还是public_手写Webpack从0编译Vue/React项目

当前前端开发,90%的项目都是Vue和React,然而70%的同学都基于脚手架创建项目,因为脚手架会包含项目基本框架、webpack配置、scss/sass/less解析、babel配置、DevServer、JSX/Vue文件解析、CSS前缀等,我们要做的就是开发功能模块&am…

python 在线预览文件_用Python PyQt写一个在线预览图片的GUI

在爬完网上一篇帖子,并得到其中的所有图片链接后,写一个GUI来实现在线预览是一个很自然的想法, 相当于实现一个python版的图片浏览器, 通过这个练习,可以让我们更熟悉PyQt这个库。这里我用的是PyQt4。以下是我的写的程…

google 确定某点海拔高_一份“高投资回报率”的用户体验度量方法指南

本文核心就是介绍体验度量方法,以及如何在商业项目中如何发起一个具有高ROI(投资回报率)的用户体验量化流程。 下面文章将分为解读高投资回报和拆解体验度量、实际案例讲解三部分。一、解读高投资回报率高ROI(投资回报率)来定义体验度量流程的原因?3-5年…

md5 java代码_JAVA简单实现MD5注册登录加密实例代码

开发环境:jdk1.7,eclipse框架:springmvc,mybatis工具:maven以下代码复制即可实现MD5加密创建一个mave项目,加web。不懂得可以搜索一下就有了。注册用户的JSP页面代码如下。pageEncoding"utf-8"%&…

一维卷积神经网络_序列特征的处理方法之二:基于卷积神经网络方法

前言上一篇文章介绍了基本的基于注意力机制方法对序列特征的处理,这篇主要介绍一下基本的基于卷积神经网络方法对序列特征的处理,也就是TextCNN方法。序列特征的介绍,背景以及应用可以参考上一篇的详细介绍,这里简单回顾一下定义&…

macos降级_iOS12.3 beta2更新了什么 iOS12.3测试版2新特性与升降级方法

4月0日凌晨,苹果发布了iOS12.3 beta2,作为iOS12.3第二个测试版,相比前一个版本,发布时间间隔近2周,这次依然是小版本更新,不过相对良心一些,主要是多了一些与国内用户相关的东西。iOS12.3 beta …

linux配置usb主从_杂集:浅谈关于Mongodb数据库主从复制

Linux下Mongodb数据库主从复制配置Mongodb的三种集群搭建的方式:Master-Slaver:主从[目前被副本集取代]。Replica Set:副本集。Sharding:切片。Mongodb单实例缺点:适合简易开发时使用,生产使用不行&#xf…

java sax xml文件解析_java解析xml文件-DOM/SAX

java解析xml文件的两种方式1:DOM原理:把整个文档加载到内存,转化成dom树,之后应用程序可以随机的访问dom树的任何数据,灵活 快,但消耗内存一个简单的xml使用java解析//builder工厂DocumentBuilderFactory f…

python 远程控制_用 Python 远程控制你的电脑

用 Python 远程控制你的电脑一、前言很多时候我们有这种需求,因为程序运行比较耗时,但是我们没有足够的时间等待。这个时候我们就可以用 Python 做一个远程控制电脑的小工具,实现远程控制电脑。当然,我们能做的操作十分有限&#…

摄像头图像分析目标物体大小位置_一文读懂图像定位及跟踪技术

文 | 传感器技术在科学技术日新月异的今天,人们对机器设备的智能性、自主性要求也越来越高,希望其完全替代人的角色,把人们从繁重、危险的工作任务中解脱出来,而能否像人一样具有感知周围环境的能力已成为设备实现智能化自主化的关…

pat乙级相当于什么水平_雅思6.5是什么水平?相当于托福多少分?

雅思和托福是当前社会中非母语人士的主流英语水平测试。准备出国留学的学生对这两项考试并不陌生。对于一些学生来说,仅靠雅思成绩并不足以申请他们最喜欢的学校。特别是对于申请北美院校的学生,托福成绩是申请时提交语言成绩的优先考虑事项。那么&#…

java时间方法_JAVA处理日期时间常用方法

转载JAVA处理日期时间常用方法:1.java.util.CalendarCalendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可…