1. 程式人生 > >9.MySQL優化Nested-Loop Join Algorithms

9.MySQL優化Nested-Loop Join Algorithms

介紹

MySQL使用巢狀迴圈演算法或其變體在表之間執行連線。

  • Nested-Loop Join Algorithm
  • Block Nested-Loop Join Algorithm

1 Nested-Loop Join Algorithm

簡單的Nested-Loop演算法意思就是,從第一張表讀取一條記錄,然後與第二張表的每一行進行迴圈比對,達成表連線目的,然後再從第一張表讀取一條記錄與第二張表的每一條進行比對,如此往復,有幾張表就有基層Nested-Loop迴圈。

舉個例子如下:

現在使用Nested-Loop連線方式連線t1、t2、t3

Table Join Type
t1 range
t2 ref
t3 ALL

如果使用簡單的NLJ演算法,則會按如下方式處理連線:

for each row in t1 matching range {
	for each row in t2 matching reference key {
		for each row in t3 {
			if row satisfies join conditions, send to client
		}
	}
}

2 Block Nested-Loop Join Algorithm

塊巢狀迴圈(BNL)連線演算法使用外部迴圈中讀取的行的緩衝來減少必須讀取內部迴圈中的表的次數。 例如,如果將10行讀入緩衝區並將緩衝區傳遞給下一個內部迴圈,則可以將內部迴圈中讀取的每一行與緩衝區中的所有10行進行比較。 這將內表必須讀取的次數減少一個數量級。

MySQL join快取具有以下特徵:

  • join_buffer_size變數決定buffer大小。
  • 只有在join型別為all, index, range的時候才可以使用join buffer。
  • 能夠被buffer的每一個join都會分配一個buffer, 也就是說一個query最終可能會使用多個join buffer。
  • 第一個nonconst table不會分配join buffer, 即便其掃描型別是all或者index。
  • 在join之前就會分配join buffer, 在query執行完畢即釋放。
  • join buffer中只會儲存參與join的列, 並非整個資料行。

bnl公式如下

for each row in t1 matching range {
	for each row in t2 matching reference key {
		store used columns from t1, t2 in join buffer
		if buffer is full {
			for each row in t3 {
				for each t1, t2 combination in join buffer {
					if row satisfies join conditions, send to client
				}
			}
			empty join buffer
		}
	}
}
if buffer is not empty {
	for each row in t3 {
		for each t1, t2 combination in join buffer {
			if row satisfies join conditions, send to client
		}
	 }
}

如果S是連線緩衝區中儲存的每個t1、t2組合的大小,而C是緩衝區中組合的數量,則掃描表t3的次數是:

(S * C)/join_buffer_size + 1

224/5000
隨著join_buffer_size的值增加,t3掃描的數量減少,直到join_buffer_size足夠大以容納所有先前的行組合的點。 在那時,通過使其變大不會獲得加速。