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.pswp.cn/news/533645.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533645.shtml
英文地址,請注明出處:http://en.pswp.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以后,再購買域名和空間,真正開始你的建站之旅。…

用python慶祝生日_python, 實現朋友家人年歷生日自動提醒

為了方便提醒自己,今天有哪位朋友過生日(年歷生日)。測試環境:fedora25桌面版。建立一個生日配置文件,注意:按日期排好序vi /etc/birthday.txt朋友A 1-4朋友C 2-3朋友B 3-8創建腳本文件創建腳本文件 /usr/bin/check_birthday&…

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這個詞來自于希臘語,有主管,舵手,船長的…

mysql實現程序的動態鏈接_程序的鏈接和裝入及Linux下動態鏈接的實現

鏈接器和裝入器的基本工作原理一個程序要想在內存中運行,除了編譯之外還要經過鏈接和裝入這兩個步驟。從程序員的角度來看,引入這兩個步驟帶來的好處就是可以直接在程序中使用printf和errno這種有意義的函數名和變量名,而不用明確指明printf和…

python 二進制流_Python中對字節流/二進制流的操作:struct模塊簡易使用教程

前言前段時間使用Python解析IDX文件格式的MNIST數據集,需要對二進制文件進行讀取操作,其中我使用的是struct模塊。查了網上挺多教程都寫的挺好的,不過對新手不是很友好,所以我重新整理了一些筆記以供快速上手。注:教程…

react 圖片放在src里面還是public_手寫Webpack從0編譯Vue/React項目

當前前端開發,90%的項目都是Vue和React,然而70%的同學都基于腳手架創建項目,因為腳手架會包含項目基本框架、webpack配置、scss/sass/less解析、babel配置、DevServer、JSX/Vue文件解析、CSS前綴等,我們要做的就是開發功能模塊&am…

python union函數_如何掌握Python union()方法及怎么用?

不斷學習python的過程里,總能遇到各種形形色色的函數或者方法,本章給大家帶來python union的用法,具體內容如下:union()方法描述:union() 取并集,效果等同于 | ,重復元素只會出現一次&#xff0…

輸入分鐘輸出小時python_輸出鍵,值對如何使1小時內的時間在使用Python的MapReduce中的reducer中結束?...

這是一個策略:來自Mapper的:發出每個記錄的三個副本并使用二級排序:((復合鍵),值)((消息小時 - 一小時,當前消息的精確時間),消息)((消息小時,消息的準確時間),消息)((消息小時1小時…

python 在線預覽文件_用Python PyQt寫一個在線預覽圖片的GUI

在爬完網上一篇帖子,并得到其中的所有圖片鏈接后,寫一個GUI來實現在線預覽是一個很自然的想法, 相當于實現一個python版的圖片瀏覽器, 通過這個練習,可以讓我們更熟悉PyQt這個庫。這里我用的是PyQt4。以下是我的寫的程…

python怎樣安裝模塊_python中如何安裝模塊

下面介紹幾種安裝Python模塊的幾種方式方法1:easy_install 方式先下載ez_setup.py,運行python ez_setup 進行easy_install工具的安裝,之后就可以使用easy_install進行安裝package了。本文安裝的是Python 2.7.13版本,已經自帶了easy_install。…

java rt_java中rt包中源碼了解

javap –verbose class名 查看class文件的具體內容javap -c class名繼續看io類接口 java.io.Closeable功能:關閉流和相應的資源java.io.console功能:使用字節控制臺,與當前的java virtual machine 相關java.io.DataInput功能:從二…

google 確定某點海拔高_一份“高投資回報率”的用戶體驗度量方法指南

本文核心就是介紹體驗度量方法,以及如何在商業項目中如何發起一個具有高ROI(投資回報率)的用戶體驗量化流程。 下面文章將分為解讀高投資回報和拆解體驗度量、實際案例講解三部分。一、解讀高投資回報率高ROI(投資回報率)來定義體驗度量流程的原因?3-5年…

md5 java代碼_JAVA簡單實現MD5注冊登錄加密實例代碼

開發環境:jdk1.7,eclipse框架:springmvc,mybatis工具:maven以下代碼復制即可實現MD5加密創建一個mave項目,加web。不懂得可以搜索一下就有了。注冊用戶的JSP頁面代碼如下。pageEncoding"utf-8"%&…

一維卷積神經網絡_序列特征的處理方法之二:基于卷積神經網絡方法

前言上一篇文章介紹了基本的基于注意力機制方法對序列特征的處理,這篇主要介紹一下基本的基于卷積神經網絡方法對序列特征的處理,也就是TextCNN方法。序列特征的介紹,背景以及應用可以參考上一篇的詳細介紹,這里簡單回顧一下定義&…