搜尋
首頁資料庫mysql教程詳解MySQL JOIN原理介紹

詳解MySQL JOIN原理介紹

Jul 20, 2017 pm 03:31 PM
joinmysql原理

一. Join語法概述

join 用於多表中字段之間的聯繫,語法如下:

#... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona

table1:左表;table2:右表。

JOIN 依功能大致分為如下三類:

INNER JOIN(內連接,或等值連接):取得兩個表中存在連接匹配關係的記錄。

LEFT JOIN(左連接):取得左表(table1)完全記錄,即是右表(table2)並無對應匹配記錄。

RIGHT JOIN(右連接):與 LEFT JOIN 相反,取得右表(table2)完全記​​錄,即是左表(table1)並無匹配對應記錄。

注意:mysql不支援Full join,不過可以透過UNION 關鍵字來合併LEFT JOIN 與RIGHT JOIN來模擬FULL join.

先看一下實驗的兩張表:

表comments,總行數28856
表comments_for,總行數57,comments_id是有索引的,ID列為主鍵。
以上兩張表是我們測試的基礎,然後看一下索引,comments_for這個表comments_id是有索引的,ID為主鍵。
最近被公司某一開發問道JOIN了MySQL JOIN的問題,細數之下發下我對MySQL JOIN的理解並不是很深刻,所以也查看了很多文檔,最後在InsideMySQL公眾號看到了兩篇關於JOIN的分析,感覺寫的太好了,拿出來分享我對JOIN的實際測試吧。以下先介紹一下MySQL關於JOIN的演算法,總共分為三種(來源為InsideMySQL):
MySQL是只支援一種JOIN演算法Nested-Loop Join(嵌套循環連結),不像其他商業資料庫可以支援哈希連結和合併連接,不過MySQL的Nested-Loop Join(嵌套循環連結)也是有很多變種,能夠幫助MySQL更有效率的執行JOIN操作:
#(1)Simple Nested- Loop Join(圖片為InsideMySQL取來)
#這個演算法相對來說就是很簡單了,從驅動表中取出R1匹配S表所有列,然後R2,R3,直到將R表中的所有數據匹配完,然後合併數據,可以看到這種演算法要對S表進行RN次訪問,雖然簡單,但是相對來說開銷還是太大了
(2)Index Nested-Loop Join,實作方式如下圖:
#索引巢狀聯繫由於非驅動表上有索引,所以比較的時候不再需要一筆記錄進行比較,而可以透過索引來減少比較,從而加速查詢。這也就是平常我們在做關聯查詢的時候必須要求關聯欄位有索引的一個主要原因。
這種演算法在連結查詢的時候,驅動表會根據關聯字段的索引進行查找,當在索引上找到了符合的值,再回表進行查詢,也就是只有當匹配到索引以後才會進行回表。至於驅動表的選擇,MySQL優化器一般情況下是會選擇記錄數少的作為驅動表,但是當SQL特別複雜的時候不排除會出現錯誤選擇。
在索引巢狀連結的方式下,如果非驅動表的關聯鍵是主鍵的話,這樣來說效能就會非常的高,如果不是主鍵的話,關聯起來如果傳回的行數很多的話,效率就會特別的低,因為要多次的回表操作。先關聯索引,再根據二級索引的主鍵ID進行回表的運算。這樣來說的話性能相對就會很差。
(3)Block Nested-Loop Join,實作如下:
#在有索引的情況下,MySQL會嘗試去使用Index Nested -Loop Join演算法,在某些情況下,可能Join的列就是沒有索引,那麼這時MySQL的選擇絕對不會是最先介紹的Simple Nested-Loop Join演算法,而是會優先使用Block Nested-Loop Join的演算法.
Block Nested-Loop Join對比Simple Nested-Loop Join多了一個中間處理的過程,也就是join buffer,使用join buffer將驅動表的查詢JOIN相關列都給緩衝到了JOIN BUFFER當中,然後批次與非驅動表進行比較,這也來實現的話,可以將多次比較合併到一次,降低了非驅動表的訪問頻率。也就是只需要存取一次S表。這樣來說的話,就不會出現多次存取非驅動表的情況了,也只有這種情況下才會造訪join buffer。
在MySQL當中,我們可以透過參數join_buffer_size來設定join buffer的值,然後再進行操作。預設情況下join_buffer_size=256K,在尋找的時候MySQL會將所有的需要的列快取到join buffer當中,包括select的列,而不是只快取關聯列。在一個有N個JOIN關聯的SQL當中會在執行時候分配N-1個join buffer。
上面介紹完了,下面看一下特定的列子
(1)全表JOIN
EXPLAIN SELECT * FROM comments gc
JOIN comments_for gcf ON gc.comments_id=gcf.comments_id;

 

#看一下輸出訊息:
 
#可以看到在全表掃描的時候comments_for 作為了驅動表,此事因為關聯欄位是有索引的,所以對索引idx_commentsid進行了一個全索引掃描去匹配非驅動表comments ,每次能夠匹配到一行。此時使用的就是Index Nested-Loop Join,透過索引進行了全表的匹配,我們可以看到因為comments_for 表的量級遠小於comments ,所以說MySQL優先選擇了小表comments_for 作為了驅動表。
(2)全表JOIN+篩選條件
SELECT * FROM comments gc
JOIN comments_for gcf ON gc.comments_id=gcf.comments_id
WHERE gc.comments_id =2056

#此時使用的是Index Nested-Loop Join,先對驅動表comments 的主鍵進行篩選,符合一條,對非驅動表comments_for 的索引idx_commentsid進行seek匹配,最終匹配結果預計為影響一條,這樣就是僅僅對非驅動表的idx_commentsid索引進行了一次存取操作,效率相對來說還是非常高的。
(3)看關聯欄位是沒有索引的情況:

EXPLAIN SELECT * FROM comments gc
JOIN comments_for gcf ON gc.order_id=gcf.product_id
 
##我們來看看執行計畫:
從執行計畫我們就可以看出,這個表JOIN就是使用了Block Nested-Loop Join來進行表格關聯,先把comments_for (只有57行)這個小表作為驅動表,然後將comments_for 的需要的數據緩存到JOIN buffer當中,批量對comments 表進行掃描,也就是只進行一次匹配,前提是join buffer足夠大能夠存下comments_for的緩存數據。
而且我們看到執行計劃當中已經很明確的提示:Using where; Using join buffer (Block Nested Loop)
一般情況出現這種情況就證明我們的SQL需要優化了。

要注意的是這種情況下,MySQL也會選擇Simple Nested-Loop Join這種暴力的方法,我還沒搞懂他這個優化器是怎麼選擇的,但一般是使用Block Nested -Loop Join,因為CBO是基於開銷的,Block Nested-Loop Join的性能相對於Simple Nested-Loop Join是要好很多的。

(4)看看left join
EXPLAIN SELECT * FROM comments gc
LEFT JOIN comments_for gcf ON gc.comments_id=gcf.comments_id
看看執行計畫:
##### ###########這種情況,由於我們的關聯欄位是有索引的,所以說Index Nested-Loop Join,只不過當沒有篩選條件的時候會選擇第一張表作為驅動表去進行JOIN,去關聯非驅動表的索引進行Index Nested-Loop Join。 ######如果加上篩選條件gc.comments_id =2056的話,這樣就會篩選出一條對非驅動表進行Index Nested-Loop Join,這樣效率是很高的。 ######如果是下面這種:#########
EXPLAIN SELECT * FROM comments_for gcf
LEFT JOIN comments gc ON gc.comments_id=gcf.comments_id
WHERE gcf.comments_id =2056
###### #########透過gcf表進行篩選的話,就會預設選擇gcf表作為驅動表,因為很明顯他進行過了篩選,匹配的條件會很少,具體可以看​​下執行計劃:#########此,join基本上已經很明了,未完待續中,歡迎大家指出錯誤,我會認真改正。 。 。 。 ############ ####

以上是詳解MySQL JOIN原理介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
MySQL:世界上最受歡迎的數據庫的簡介MySQL:世界上最受歡迎的數據庫的簡介Apr 12, 2025 am 12:18 AM

MySQL是一種開源的關係型數據庫管理系統,主要用於快速、可靠地存儲和檢索數據。其工作原理包括客戶端請求、查詢解析、執行查詢和返回結果。使用示例包括創建表、插入和查詢數據,以及高級功能如JOIN操作。常見錯誤涉及SQL語法、數據類型和權限問題,優化建議包括使用索引、優化查詢和分錶分區。

MySQL的重要性:數據存儲和管理MySQL的重要性:數據存儲和管理Apr 12, 2025 am 12:18 AM

MySQL是一個開源的關係型數據庫管理系統,適用於數據存儲、管理、查詢和安全。 1.它支持多種操作系統,廣泛應用於Web應用等領域。 2.通過客戶端-服務器架構和不同存儲引擎,MySQL高效處理數據。 3.基本用法包括創建數據庫和表,插入、查詢和更新數據。 4.高級用法涉及復雜查詢和存儲過程。 5.常見錯誤可通過EXPLAIN語句調試。 6.性能優化包括合理使用索引和優化查詢語句。

為什麼要使用mysql?利益和優勢為什麼要使用mysql?利益和優勢Apr 12, 2025 am 12:17 AM

選擇MySQL的原因是其性能、可靠性、易用性和社區支持。 1.MySQL提供高效的數據存儲和檢索功能,支持多種數據類型和高級查詢操作。 2.採用客戶端-服務器架構和多種存儲引擎,支持事務和查詢優化。 3.易於使用,支持多種操作系統和編程語言。 4.擁有強大的社區支持,提供豐富的資源和解決方案。

描述InnoDB鎖定機制(共享鎖,獨家鎖,意向鎖,記錄鎖,間隙鎖,下一鍵鎖)。描述InnoDB鎖定機制(共享鎖,獨家鎖,意向鎖,記錄鎖,間隙鎖,下一鍵鎖)。Apr 12, 2025 am 12:16 AM

InnoDB的鎖機制包括共享鎖、排他鎖、意向鎖、記錄鎖、間隙鎖和下一個鍵鎖。 1.共享鎖允許事務讀取數據而不阻止其他事務讀取。 2.排他鎖阻止其他事務讀取和修改數據。 3.意向鎖優化鎖效率。 4.記錄鎖鎖定索引記錄。 5.間隙鎖鎖定索引記錄間隙。 6.下一個鍵鎖是記錄鎖和間隙鎖的組合,確保數據一致性。

MySQL查詢性能差的常見原因是什麼?MySQL查詢性能差的常見原因是什麼?Apr 12, 2025 am 12:11 AM

MySQL查询性能不佳的原因主要包括没有使用索引、查询优化器选择错误的执行计划、表设计不合理、数据量过大和锁竞争。1.没有索引导致查询缓慢,添加索引后可显著提升性能。2.使用EXPLAIN命令可以分析查询计划,找出优化器错误。3.重构表结构和优化JOIN条件可改善表设计问题。4.数据量大时,采用分区和分表策略。5.高并发环境下,优化事务和锁策略可减少锁竞争。

您什麼時候應該使用複合索引與多個單列索引?您什麼時候應該使用複合索引與多個單列索引?Apr 11, 2025 am 12:06 AM

在數據庫優化中,應根據查詢需求選擇索引策略:1.當查詢涉及多個列且條件順序固定時,使用複合索引;2.當查詢涉及多個列但條件順序不固定時,使用多個單列索引。複合索引適用於優化多列查詢,單列索引則適合單列查詢。

如何識別和優化MySQL中的慢速查詢? (慢查詢日誌,performance_schema)如何識別和優化MySQL中的慢速查詢? (慢查詢日誌,performance_schema)Apr 10, 2025 am 09:36 AM

要優化MySQL慢查詢,需使用slowquerylog和performance_schema:1.啟用slowquerylog並設置閾值,記錄慢查詢;2.利用performance_schema分析查詢執行細節,找出性能瓶頸並優化。

MySQL和SQL:開發人員的基本技能MySQL和SQL:開發人員的基本技能Apr 10, 2025 am 09:30 AM

MySQL和SQL是開發者必備技能。 1.MySQL是開源的關係型數據庫管理系統,SQL是用於管理和操作數據庫的標準語言。 2.MySQL通過高效的數據存儲和檢索功能支持多種存儲引擎,SQL通過簡單語句完成複雜數據操作。 3.使用示例包括基本查詢和高級查詢,如按條件過濾和排序。 4.常見錯誤包括語法錯誤和性能問題,可通過檢查SQL語句和使用EXPLAIN命令優化。 5.性能優化技巧包括使用索引、避免全表掃描、優化JOIN操作和提升代碼可讀性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。