14.MySQL優化Block Nested-Loop and Batched Key Access Joins
介紹
在MySQL中,Batched Key Access (BKA) Join algorithm該演算法用於對聯接表和連線緩衝區的索引訪問。BKA演算法支援內連線,外連線和半連線操作,包括巢狀外連線。BKA的優點包括由於更高效的表掃描而提高了連線效能。此外,先前僅用於內連線的塊巢狀迴圈(BNL)連線演算法已擴充套件,可用於外連線和半連線操作,包括巢狀外連線。
以下部分討論了連線緩衝區管理,它是原始BNL演算法擴充套件,擴充套件BNL演算法和BKA演算法的基礎。
- Join Buffer Management for Block Nested-Loop and Batched Key Access Algorithms 加入塊巢狀迴圈和批量金鑰訪問演算法的緩衝區管理
- Block Nested-Loop Algorithm for Outer Joins and Semi-Joins 用於外連線和半連線的塊巢狀迴圈演算法
- Batched Key Access Joins 批量金鑰訪問連線
- Optimizer Hints for Block Nested-Loop and Batched Key Access Algorithms 塊巢狀迴圈和批量金鑰訪問演算法的優化器提示
1 Join Buffer Management for Block Nested-Loop and Batched Key Access Algorithms
MySQL可以使用連線緩衝區不僅可以執行內部聯接而無需對內部表進行索引訪問,還可以執行子查詢展平後出現的外部聯接和半聯接。此外,當存在對內部表的索引訪問時,可以有效地使用連線緩衝區。
當儲存感興趣的行列的值時,連線緩衝區管理程式碼更有效地利用連線緩衝區:如果行的值為NULL,則不在緩衝區中為行列分配額外位元組,並且對varchar型別的每一個值分配最小的位元組。
他定義了兩種型別的緩衝區:常規緩衝區和增量緩衝區。假設表t1與t2連線的時候使用連線緩衝區B1,然後他們的結果與表t3連線使用連線緩衝區B2:
- 常規連線緩衝區包含來自每個連線運算元的列。如果B2是一個常規的連線緩衝區,放入B2中的每一行r由來自B1的行r1的列和來自表t3的匹配行r2的有趣列組成。
- 增量連線緩衝區僅包含第二個連線運算元生成的錶行中的列。也就是說,它是第一個運算元緩衝區中一行的增量。假如B2是一個增量緩衝區,它包含感興趣的行r2和在B1緩衝區t1的一個link。
增量連線緩衝區始終相對於早期連線操作的連線緩衝區是增量的,因此第一個連線操作的緩衝區始終是常規緩衝區。在剛剛給出的例項中,緩衝B1 用來連線表t1和 t2必須是常規緩衝區。
增量緩衝區用於一個連線操作中包含被連線的表中的一行當中他感興趣的列。有第一個連線產生的表中的匹配的行中它感興趣的列進行擴充。增量緩衝區中的若干行可以引用同一行r,只要所有這些行都匹配行r,則該行r的列儲存在先前的連線緩衝區中。
增量緩衝區可以減少從先前連線操作使用的緩衝區中複製列的頻率。這節省了緩衝區空間,因為在一般情況下,第一個連線運算元產生的行可以由第二個連線運算元產生的幾個行匹配。不必從第一個運算元生成一行的多個副本。由於複製時間的減少,增量緩衝區還可以節省處理時間。
系統變數 的block_nested_loop和 batched_key_access標誌 optimizer_switch控制優化器如何使用塊巢狀迴圈和批量金鑰訪問連線演算法。
3 Block Nested-Loop Algorithm for Outer Joins and Semi-Joins
MySQL BNL演算法的原始實現被擴充套件為支援外連線和半連線操作。
當使用連線緩衝區執行這些操作時,每個放入緩衝區的行都會提供一個匹配標誌。
如果使用連線緩衝區執行外連線操作,則檢查第二個運算元生成的表的每一行是否與連線緩衝區中的每一行匹配。找到匹配項後,將形成一個新的擴充套件行(原始行加上第二個運算元中的列),並通過其餘的連線操作傳送以進一步擴充套件。此外,啟用緩衝區中匹配行的匹配標誌。在檢查了要連線的表的所有行之後,將掃描連線緩衝區。緩衝區中沒有啟用匹配標誌的每一行都由NULL補充擴充套件(NULL 第二個運算元中每列的值),並由剩餘的連線操作傳送以進一步擴充套件。
系統變數 的block_nested_loop標誌 optimizer_switch控制優化器如何使用塊巢狀迴圈演算法。
在EXPLAIN輸出時,使用BNL時Extra中會包含Using join buffer (Block Nested Loop),type的值是ALL, index,或 range。
4 Batched Key Access Joins
MySQL實現了一種連線表的方法,叫做Batched Key Access(BKA),當存在對第二個連線運算元生成的表的索引訪問時,可以應用BKA。像BNL演算法一樣,BKA演算法採用連線緩衝區積累由連線操作產生的第一個的行中的感興趣的列。然後BKA演算法建立KEY到表的訪問在緩衝區中連線所有行,,並將這些KEY批量提交到資料庫引擎以進行索引查詢。在提交key之後,MRR引擎函式以最佳方式在索引中執行查詢,獲取由這些金鑰找到的連線表的行,並開始向匹配行提供BKA連線演算法。每個匹配行與對連線緩衝區中的行的引用相耦合。
使用BKA時,值join_buffer_size定義了每個請求到儲存引擎的批量金鑰的大小。緩衝區越大,對連線操作的右側表的順序訪問就越多,這可以顯著提高效能。
要使用BKA,必須將系統變數的batched_key_access標誌 optimizer_switch設定為on。BKA使用MRR,因此mrr標誌也必須是 on。目前,MRR的成本估算過於悲觀。因此,也有必要對 mrr_cost_based要 off用於要使用的BKA。以下設定啟用BKA:
mysql> SET optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';
MRR功能有兩種執行方式:
- 第一種方案用於傳統的基於磁碟的儲存引擎,例如InnoDB和 MyISAM。對於這些引擎,通常將來自連線緩衝區的所有行的鍵一次提交給MRR介面。特定於引擎的MRR函式對提交的金鑰執行索引查詢,從中獲取行ID(或主鍵),然後根據BKA演算法的請求逐個獲取所有這些選定行ID的行。返回的每一行都帶有一個關聯引用,該引用允許訪問連線緩衝區中的匹配行。MRR函式以最佳方式獲取行:它們以行ID(主鍵)順序獲取。這提高了效能,因為讀取是按磁碟順序而不是隨機順序。
- 第二種方案用於遠端儲存引擎,例如NDB。來自連線緩衝區的一部分行的金鑰包及其關聯由MySQL伺服器(SQL節點)傳送到MySQL Cluster資料節點。作為回報,SQL節點接收匹配行的包(或多個包)以及相應的關聯。BKA連線演算法獲取這些行並構建新的連線行。然後將一組新金鑰傳送到資料節點,並使用返回的包中的行來構建新的連線行。該過程將繼續,直到將來自聯接緩衝區的最後一個金鑰傳送到資料節點,並且SQL節點已接收並加入與這些金鑰匹配的所有行。
對於第一種情況,保留一部分連線緩衝區以儲存由索引查詢選擇的行ID(主鍵),並作為引數傳遞給MRR功能。
沒有特殊的緩衝區來儲存為連線緩衝區中的行構建的金鑰。相反,為緩衝區中的下一行構建鍵的函式作為引數傳遞給MRR函式。
在EXPLAIN輸出中,使用BKA時Extra顯示的值是Using join buffer (Batched Key Access),type的值是 ref或者eq_ref.
5 Optimizer Hints for Block Nested-Loop and Batched Key Access Algorithms
除了使用 optimizer_switch系統變數控制優化器在會話範圍內使用BNL和BKA演算法之外,MySQL還支援優化器提示以基於每個語句影響優化器。