日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

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

發(fā)布時(shí)間:2024/1/23 数据库 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql的join算法_mysql的Join算法-阿里云开发者社区 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

實(shí)為吾之愚見,望諸君酌之!聞過則喜,與君共勉

測試數(shù)據(jù)

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行數(shù)據(jù)

事例查詢

select e.to_date,d.dept_name from dept_emp

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

這是一個(gè)兩表join的query,對應(yīng)條件是where e.dept_no=d.dept_no,主要找出表dept_emp和departments中,滿足dept_no相等的記錄,然后展示出e.to_date,d.dept_name列其中dept_emp有331603行記錄,departments有9行數(shù)據(jù)

執(zhí)行計(jì)劃對比

關(guān)閉block_nested_loop

打開block_nested_loop

打開batched_key_access

Nested-Loop事例

Nested-Loop Join

關(guān)閉設(shè)置optimizer_switch的block_nested_loop為off,然后查看查詢的執(zhí)行計(jì)劃

從上圖可知,執(zhí)行計(jì)劃對departments是全表掃描(9行數(shù)據(jù)),對dept_emp也是全表掃描(331570行數(shù)據(jù)),當(dāng)使用Nested-Loop Join算法的時(shí)候,先逐行的讀取departments表(此處是全表掃描,僅限于該sql),針對departments的每一行數(shù)據(jù),都對表dept_emp的每一行記錄進(jìn)行匹配(此處是全表掃描,僅限于該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每一行做條件匹配,查找符合條件的行,反復(fù)循環(huán),直至departments的記錄掃描完成(最后一條記錄rown與dept_emp的每一行都進(jìn)行了條件匹配)

Block_nested_loop

先打開設(shè)置optimizer_switch的block_nested_loop為on,然后查看查詢的執(zhí)行計(jì)劃

從上圖可知,執(zhí)行計(jì)劃對departments是全表掃描(9行數(shù)據(jù)),對dept_emp也是全表掃描(331570行數(shù)據(jù)),但是extra列多了一部分” Using join buffer (Block Nested Loop)”,當(dāng)使用Block

Nested-Loop Join算法的時(shí)候,先逐行的讀取departments表(此處是全表掃描,僅限于該sql),然后把讀取的數(shù)據(jù),存儲到j(luò)oin buffer里(如果join buffer足夠大,就可以一次全部存儲departments所需要的join對象了,如果join buffer太小,一次只可以緩存departments的一部分join對象的話,就需要分多次進(jìn)行緩存departments的join對象),針對join buffer中緩存的數(shù)據(jù)(注意之前的一次緩存以及多次緩存),批量(不需要與Nested-Loop Join一樣,一條條的比較了,可以多條比較了)的對表dept_emp的每一行記錄進(jìn)行匹配(此處是全表掃描,僅限于該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

過程概括如下圖:

當(dāng)為dept_emp表的列dept_no添加一個(gè)索引的時(shí)候(二級索引,已經(jīng)有主鍵索引),再觀察執(zhí)行計(jì)劃:

Join type從all變成了ref,可以理解為對dept_emp執(zhí)行join的時(shí)候,使用索引進(jìn)行匹配(對應(yīng)之前的全表掃描),這里預(yù)估的行數(shù)是20723rows,比之前的331570rows少了很多(全表掃描),執(zhí)行計(jì)劃從全表掃描和ref(join type)中,選擇了

ref,對比之前的block_nested_loop,過程變化如下:

由于dept_emp下的dept_no是二級索引,查詢中又查詢了e.to_date(單單從二級索引里獲取不到數(shù)據(jù)),于是需要通過索引,查詢表里面對應(yīng)的e.to_date的值,這是如上圖可知,訪問時(shí)隨機(jī)的(圖例的表現(xiàn)方式是row1對應(yīng)pk2,row2對應(yīng)pk1等等),可能會產(chǎn)生隨機(jī)io,如果不查詢e.to_date,則不需要再去表里查詢了,同時(shí)Extra會顯示Using index,如下:

Batched_key_access

在Block_nested_loop最后部分,使用二級索引查詢的時(shí)候,出現(xiàn)了一個(gè)現(xiàn)象:當(dāng)獲取的數(shù)據(jù)二級索引無法滿足時(shí),需要去查詢原始的數(shù)據(jù)表來確定數(shù)據(jù),查詢數(shù)據(jù)是通過主鍵去查的,會出現(xiàn)不是按照主鍵順序查的情況,如果有辦法把這些無序的主鍵查詢轉(zhuǎn)換成有序的去查詢表的數(shù)據(jù)(聚簇索引),會節(jié)省很多的時(shí)間,mysql提供了Batched_key_access算法來實(shí)現(xiàn)這個(gè)需求,復(fù)現(xiàn)如下:

對比之前的Block_nested_loop(有索引和沒有索引兩部分),上面加索引后,開啟了mrr,batched_key_access,同時(shí)關(guān)閉了mrr_cost_based,這個(gè)時(shí)候Extra列出現(xiàn)了Using join buffer (Batched Key Access),使用Batched_key_access的過程如下:

上圖看,join buffer會緩存departments相關(guān)的join列,Batched_key_access算法會使用dept_no二級索引去查找,由于是無序的,查找前把這些key(可以大概理解為主鍵信息+join buffer里行的標(biāo)識信息)的信息反饋給mrr 去,mrr會按照主鍵(沒有主鍵使用row id)排序,然后順序的去dept_emp里去查找信息,并發(fā)信息再次反饋給Batched_key_access算法去和join buffer里的row進(jìn)行比較

總結(jié)

以上是生活随笔為你收集整理的mysql的join算法_mysql的Join算法-阿里云开发者社区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。