色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

介紹3種實現(xiàn)Nested-Loop Join算法的方法

冬至子 ? 來源:后端元宇宙 ? 作者:binron ? 2022-11-17 11:56 ? 次閱讀

在MySQL的實現(xiàn)中,Nested-Loop Join有3種實現(xiàn)的算法

  • Simple Nested-Loop Join:簡單嵌套循環(huán)連接
  • Block Nested-Loop Join:緩存塊嵌套循環(huán)連接
  • Index Nested-Loop Join:索引嵌套循環(huán)連接

一、原理篇

1、Simple Nested-Loop Join

比如:

SELECT *
FROM user u
 LEFT JOIN class c ON u.id = c.user_id

我們來看一下當(dāng)進(jìn)行 join 操作時,mysql是如何工作的:

圖片

當(dāng)我們進(jìn)行l(wèi)eft join連接操作時,左邊的表是 「驅(qū)動表」 ,右邊的表是**「被驅(qū)動表」**

特點

Simple Nested-Loop Join 簡單粗暴容易理解,就是通過雙層循環(huán)比較數(shù)據(jù)來獲得結(jié)果,但是這種算法顯然太過于粗魯,如果每個表有1萬條數(shù)據(jù),那么對數(shù)據(jù)比較的次數(shù)=1萬 * 1萬 =1億次,很顯然這種查詢效率會非常慢。

「這個全是磁盤掃描!」

?因為每次從驅(qū)動表取數(shù)據(jù)比較耗時,所以MySQL即使在沒有索引命中的情況下也并沒有采用這種算法來進(jìn)行連接操作,而是下面這種!

?

2、Block Nested-Loop Join

同樣以上面的sql為例,我們看下mysql是如何工作的

SELECT *
FROM user u
 LEFT JOIN class c ON u.id = c.user_id

圖片

因為每次從驅(qū)動表取一條數(shù)據(jù)都是磁盤掃描所有比較耗時。

這里就做了優(yōu)化就是 「每次從驅(qū)動表取一批數(shù)據(jù)放到內(nèi)存中,然后對這一批數(shù)據(jù)進(jìn)行匹配操作」

這批數(shù)據(jù)匹配完畢,再從驅(qū)動表中取一批數(shù)據(jù)放到內(nèi)存中,直到驅(qū)動表的數(shù)據(jù)全都匹配完畢。

這塊內(nèi)存在MySQL中有一個專有的名詞,叫做 join buffer,我們可以執(zhí)行如下語句查看 join buffer 的大小

show variables like '%join_buffer%'

圖片

另外,Join Buffer緩存的對象是什么,這個問題相當(dāng)關(guān)鍵和重要。

?Join Buffer存儲的并不是驅(qū)動表的整行記錄,具體指所有參與查詢的列都會保存到Join Buffer,而不是只有Join的列。

?

比如下面sql

SELECT a.col3
FROM a JOIN b ON a.col1 = b.col2
WHERE a.col2 > 0 AND b.col2 = 0

上述SQL語句的驅(qū)動表是a,被驅(qū)動表是b,那么存放在Join Buffer中的列是所有參與查詢的列,在這里就是(a.col1,a.col2,a.col3)。

也就是說查詢的字段越少,Join Buffer可以存的記錄也就越多!

變量join_buffer_size的默認(rèn)值是256K,顯然對于稍復(fù)雜的SQL是不夠用的。好在這個是會話級別的變量,可以在執(zhí)行前進(jìn)行擴(kuò)展。

建議在會話級別進(jìn)行設(shè)置,而不是全局設(shè)置,因為很難給一個通用值去衡量。另外,這個內(nèi)存是會話級別分配的,如果設(shè)置不好容易導(dǎo)致因無法分配內(nèi)存而導(dǎo)致的宕機(jī)問題。

-- 調(diào)整到1M
set session join_buffer_size = 1024 * 1024 * 1024;
-- 再執(zhí)行查詢
SELECT a.col3
FROM a JOIN b ON a.col1 = b.col2
WHERE a.col2 > 0 AND b.col2 = 0

3、Index Nested-Loop Join

當(dāng)我們了解**「Block Nested-Loop Join」** 算法,我們發(fā)現(xiàn)雖然可以將驅(qū)動表的數(shù)據(jù)放入 「Join Buffer」 中,但是緩存中的每條記錄都要和被驅(qū)動表的所有記錄都匹配一遍,也會非常耗時,所以我們應(yīng)該如何提高被驅(qū)動表匹配的效率呢?

其實很簡單 就是給被驅(qū)動表連接的列加上索引,這樣匹配的過程就非常快,如圖所示

圖片

上面圖中就是先匹配索引看有沒有命中的數(shù)據(jù),有命中數(shù)據(jù)再回表查詢這條記錄,獲取其它所需要的數(shù)據(jù),但列的數(shù)據(jù)在索引中都能獲取那都不需要回表查詢,效率更高!

二、SQL示例

1、新增表和填充數(shù)據(jù)

-- 表1 a字段加索引 b字段沒加
CREATE TABLE `t1` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `a` int DEFAULT NULL COMMENT '字段a',
  `b` int DEFAULT NULL COMMENT '字段b',
  PRIMARY KEY (`id`),
  KEY `idx_a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 表2
 create table t2 like t1;
-- t1插入10000條數(shù)據(jù) t2插入100條數(shù)據(jù)
 drop procedure if exists insert_data;
 delimiter ;;
 create procedure insert_data()
 begin
 declare i int;
 set i = 1;
 while ( i <= 10000 ) do
 insert into t1(a,b) values(i,i);
  set i = i + 1;
 end while;
 set i = 1;
 while ( i <= 100) do
 insert into t2(a,b) values(i,i);
  set i = i + 1;
 end while;
 end;;
 delimiter ;
 call insert_data();

2、Block Nested-Loop Join算法示例

-- b字段沒有索引
explain select t2.* from t1 inner join t2 on t1.b= t2.b; 
-- 執(zhí)行結(jié)果
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                                              |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+----------------------------------------------------+
|  1 | SIMPLE      | t2    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   100 |   100.00 | NULL                                               |
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10337 |    10.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+----------------------------------------------------+

從執(zhí)行計劃我們可以得出一些結(jié)論:

  • 驅(qū)動表是t2,被驅(qū)動表是t1。所以使用 inner join 時,排在前面的表并不一定就是驅(qū)動表。
  • Extra 中 的 「Using join buffer (Block Nested Loop)」 說明該關(guān)聯(lián)查詢使用的是 BNLJ 算法。

上面的sql大致流程是:

  1. 將 t2 的所有數(shù)據(jù)放入到 join_buffer
  2. 將 join_buffer 中的每一條數(shù)據(jù),跟表t1中所有數(shù)據(jù)進(jìn)行比較
  3. 返回滿足join 條件的數(shù)據(jù)

3、Index Nested-Loop Join 算法

-- a字段有索引
EXPLAIN select * from t1 inner join t2 on t1.a= t2.a;   
-- 執(zhí)行結(jié)果
+----+-------------+-------+------------+------+---------------+-------+---------+-----------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key   | key_len | ref             | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+-------+---------+-----------------+------+----------+-------------+
|  1 | SIMPLE      | t2    | NULL       | ALL  | idx_a         | NULL  | NULL    | NULL            |  100 |   100.00 | Using where |
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_a         | idx_a | 5       | mall_order.t2.a |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+------+---------------+-------+---------+-----------------+------+----------+-------------+

從執(zhí)行計劃我們可以得出一些結(jié)論:

  • 我們可以看出 t1的type不在是all而是ref,說明不在是全表掃描,而是走了idx_a的索引。
  • 這里并沒有出現(xiàn) 「Using join buffer (Block Nested Loop)」 ,說明走的是Index Nested-Loop Join。

上面的sql大致流程是:

  1. 從表 t2 中讀取一行數(shù)據(jù)
  2. 從第 1 步的數(shù)據(jù)中,取出關(guān)聯(lián)字段 a,到表 t1 idx_a 索引中查找;
  3. 從idx_a 索引上找到滿足條件的數(shù)據(jù),如果查詢數(shù)據(jù)在索引樹都能找到,那就可以直接返回,否則回表查詢剩余字段屬性再返回。
  4. 返回滿足join 條件的數(shù)據(jù)

我們發(fā)現(xiàn)這里效率最大的提升在于,t1表中rows=1,也就是說因為idx_a 索引的存在,不需要把t1每條數(shù)據(jù)都遍歷一遍,而是通過索引1次掃描可以認(rèn)為最終只掃描 t1 表一行完整數(shù)據(jù)。

三、join優(yōu)化總結(jié)

根據(jù)上面的知識點我們可以總結(jié)以下有關(guān)join優(yōu)化經(jīng)驗:

  1. 在關(guān)聯(lián)查詢的時候,盡量在被驅(qū)動表的關(guān)聯(lián)字段上加索引,讓MySQL做join操作時盡量選擇INLJ算法

2)小表做驅(qū)動表!

當(dāng)使用left join時,左表是驅(qū)動表,右表是被驅(qū)動表,當(dāng)使用right join時,右表是驅(qū)動表,左表是被驅(qū)動表,當(dāng)使用join時,mysql會選擇數(shù)據(jù)量比較小的表作為驅(qū)動表,大表作為被驅(qū)動表,如果說我們在 join的時候 明確知道哪張表是小表的時候,可以用 「straight_join」 寫法固定連接驅(qū)動方式,省去mysql優(yōu)化器自己判斷的時間。

「對于小表定義的明確」

在決定哪個表做驅(qū)動表的時候,應(yīng)該是兩個表按照各自的條件過濾,過濾完成之后,計算參與 join 的各個字段的總數(shù)據(jù)量,數(shù)據(jù)量小的那個表,就是“小表”,應(yīng)該作為驅(qū)動表。

3)在適當(dāng)?shù)那闆r下增大 join buffer 的大小,當(dāng)然這個最好是在會話級別的增大,而不是全局級別

4)不要用 * 作為查詢列表,只返回需要的列!

這樣做的好處可以讓在相同大小的join buffer可以存更多的數(shù)據(jù),也可以在存在索引的情況下盡可能避免回表查詢數(shù)據(jù)。

審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    829

    瀏覽量

    26674
收藏 人收藏

    評論

    相關(guān)推薦

    FFT 算法的一 FPGA 實現(xiàn)

    FPGA實現(xiàn)的 FFT 處理器的硬件結(jié)構(gòu)。接收單元采用乒乓RAM 結(jié)構(gòu), 擴(kuò)大了數(shù)據(jù)吞吐量。中間數(shù)據(jù)緩存單元采用雙口RAM , 減少了訪問RAM 的時鐘消耗。計算單元采用基 2 算法, 流水線結(jié)構(gòu), 可在
    發(fā)表于 11-21 15:55

    DSP的實現(xiàn)方法

    芯片內(nèi)部用硬件實現(xiàn),無需進(jìn)行編程。在上述幾種方法中,第1種方法的缺點是速度較慢,一般可用于DSP算法的模擬;第2和第5
    發(fā)表于 08-27 13:47

    典型的ADRC算法介紹

    前言??上篇中詳細(xì)闡述了經(jīng)典的自抗擾控制算法的原理,本篇將圍繞兩ADRC算法展開,針對擴(kuò)張狀態(tài)觀測器的參數(shù)整定問題進(jìn)行詳解,同時,對跟蹤微分器的幾個重要應(yīng)用進(jìn)行介紹。兩
    發(fā)表于 09-07 08:02

    Apriori算法的一優(yōu)化方法

    介紹關(guān)聯(lián)規(guī)則挖掘中的經(jīng)典算法――Apriori算法的關(guān)鍵思想。針對傳統(tǒng)Apriori算法效率上的不足,提出一改進(jìn)的Apriori
    發(fā)表于 04-10 08:48 ?19次下載

    3DES算法的FPGA高速實現(xiàn)

    摘要:介紹3-DES算法的概要;以Xilinx公司SPARTANII結(jié)構(gòu)的XC2S100為例,闡述用FPGA高速實現(xiàn)3-DES
    發(fā)表于 06-20 14:22 ?1464次閱讀
    <b class='flag-5'>3</b>DES<b class='flag-5'>算法</b>的FPGA高速<b class='flag-5'>實現(xiàn)</b>

    Viterbi譯碼器回溯算法實現(xiàn)

    該文介紹了兩Viterbi 譯碼器回溯譯碼算法,通過對這兩算法硬件實現(xiàn)結(jié)構(gòu)上的優(yōu)化,給出了這
    發(fā)表于 05-28 15:18 ?33次下載
    Viterbi譯碼器回溯<b class='flag-5'>算法</b><b class='flag-5'>實現(xiàn)</b>

    3像素歷遍方法的比較和實現(xiàn)_Delphi教程

    Delphi教程3像素歷遍方法的比較和實現(xiàn),很好的Delphi的學(xué)習(xí)資料。
    發(fā)表于 03-16 14:55 ?4次下載

    Join在Spark中是如何組織運行的

    ,我們有必要了解Join在Spark中是如何組織運行的。 SparkSQL總體流程介紹 在闡述Join實現(xiàn)之前,我們首先簡單介紹SparkS
    的頭像 發(fā)表于 09-25 11:35 ?2260次閱讀
    <b class='flag-5'>Join</b>在Spark中是如何組織運行的

    SQL子查詢優(yōu)化是怎么回事

    子查詢 (Subquery)的優(yōu)化一直以來都是 SQL 查詢優(yōu)化中的難點之一。 關(guān)聯(lián)子查詢的基本執(zhí)行方式類似于 Nested-Loop,但是這種執(zhí)行方式的效率常常低到難以忍受。 當(dāng)數(shù)據(jù)量稍大時,必須
    的頭像 發(fā)表于 02-01 13:55 ?2084次閱讀
    SQL子查詢優(yōu)化是怎么回事

    介紹3種方法跨時鐘域處理方法

    介紹3跨時鐘域處理的方法,這3種方法可以說是FPGA界最常用也最實用的
    的頭像 發(fā)表于 09-18 11:33 ?2.2w次閱讀
    <b class='flag-5'>介紹</b><b class='flag-5'>3</b><b class='flag-5'>種方法</b>跨時鐘域處理<b class='flag-5'>方法</b>

    LOOP指令——匯編語言學(xué)習(xí)筆記3

    實現(xiàn)乘法的例子四、總結(jié)LOOP功能與格式功能:實現(xiàn)循環(huán)(計數(shù)型循環(huán))指令格式:LOOP 標(biāo)號一、LOOP指令實例以下是一個
    發(fā)表于 01-18 08:30 ?4次下載
    <b class='flag-5'>LOOP</b>指令——匯編語言學(xué)習(xí)筆記<b class='flag-5'>3</b>

    如何優(yōu)化MySQL中的join語句

    在mysql中,join 主要有Nested Loop、Hash Join、Merge Join 這三
    的頭像 發(fā)表于 04-24 17:03 ?841次閱讀
    如何優(yōu)化MySQL中的<b class='flag-5'>join</b>語句

    一文終結(jié)SQL子查詢優(yōu)化

    子查詢(Subquery)的優(yōu)化一直以來都是 SQL 查詢優(yōu)化中的難點之一。關(guān)聯(lián)子查詢的基本執(zhí)行方式類似于 Nested-Loop,但是這種執(zhí)行方式的效率常常低到難以忍受。
    的頭像 發(fā)表于 04-28 14:19 ?790次閱讀
    一文終結(jié)SQL子查詢優(yōu)化

    大模型+多模態(tài)的3實現(xiàn)方法

    我們知道,預(yù)訓(xùn)練LLM已經(jīng)取得了諸多驚人的成就, 然而其明顯的劣勢是不支持其他模態(tài)(包括圖像、語音、視頻模態(tài))的輸入和輸出,那么如何在預(yù)訓(xùn)練LLM的基礎(chǔ)上引入跨模態(tài)的信息,讓其變得更強(qiáng)大、更通用呢?本節(jié)將介紹“大模型+多模態(tài)”的3
    的頭像 發(fā)表于 12-13 13:55 ?1780次閱讀
    大模型+多模態(tài)的<b class='flag-5'>3</b><b class='flag-5'>種</b><b class='flag-5'>實現(xiàn)</b><b class='flag-5'>方法</b>

    arduino如何停止loop循環(huán)

    退出這個循環(huán)。本文將詳細(xì)介紹如何在Arduino中停止loop循環(huán)。 在Arduino中,可以通過使用一個布爾變量或條件語句來實現(xiàn)停止loop循環(huán)的功能。下面我們將逐步討論這些
    的頭像 發(fā)表于 02-14 16:24 ?4668次閱讀
    主站蜘蛛池模板: 8x8x我要打机飞在线观看 | 五月丁香婷姐色 | 国产亚洲精品久久孕妇呦呦你懂 | youjizz护士| 久久综合久综合久久鬼色 | 亚洲天堂一区二区三区 | 国产精品野外AV久久久 | 国产精品自在自线亚洲 | 女生下面免费看 | 男同志china免费视频 | 天天插天天舔 | 国产精品成人免费观看 | 一本道高清到手机在线 | 无人区免费一二三四乱码 | 日日碰狠狠躁久久躁综合网 | 18动漫在线观看 | 久久成人永久免费播放 | 精品熟女少妇AV免费观看 | 国产精品自产拍在线观看网站 | 青青青青草 | 青青草色青伊人 | 国产曰韩无码亚洲视频 | 天堂精品国产自在自线 | 午夜福到在线4国产 | 欧美丰满熟妇无码XOXOXO | 亚洲午夜福利未满十八勿进 | 国产1769一七六九视频在线 | 美女穿丝袜被狂躁动态图 | 国产精品久久久久久久人人看 | 99视频在线观看免费 | p影院永久免费 | 一区二区三区高清视频 | 猪蜜蜜网站在线观看电视剧 | 亚洲午夜精品A片久久WWW软件 | 少爷被多个暗卫肉高h | 一攻多受高h大总攻 | 成人国产亚洲欧美成人综合网 | 成人免费一级毛片在线播放视频 | 国产亚洲精品品视频在线 | 人妖欧美一区二区三区四区 | 欧美深深色噜噜狠狠yyy |