(十三)Join原理,Join優化

2021-10-08 21:36:29 字數 1797 閱讀 9870

聯結兩個表時,如果第二個表上有聯結鍵索引,那麼就會根據第乙個表中查出的聯結鍵值搜尋索引,然後根據索引得到的主鍵id去第二張表找

在這種情況下:

使用 join 語句,效能比強行拆成多個單錶執行 sql 語句的效能要好;

如果使用 join 語句的話,需要讓小表做驅動表。

聯結兩個表時,如果第二個表上沒有聯結鍵索引,那麼就會根據第乙個表中查出的聯結鍵值,去第二張表上作全表掃瞄

對於上面這種情況,mysql使用了 block nested-loop join

把錶 t1 的資料讀入執行緒記憶體 join_buffer 中,由於我們這個語句中寫的是 select *,因此是把整個表 t1 放入了記憶體;

掃瞄表 t2,把錶 t2 中的每一行取出來,跟 join_buffer 中的資料做對比,滿足 join 條件的,作為結果集的一部分返回。

從時間複雜度上來說,這兩個演算法是一樣的。但是,block nested-loop join 演算法的判斷是記憶體操作,速度上會快很多,效能也更好。

join_buffer 的大小是由引數 join_buffer_size 設定的,預設值是 256k。如果放不下表 t1 的所有資料話,策略很簡單,就是分段放。在使用小表作驅動表時,被驅動表的掃瞄次數更少。

大表 join 操作雖然對 io 有影響,但是在語句執行結束後,對 io 的影響也就結束了。但是,對 buffer pool 的影響就是持續性的,可能會導致 buffer pool 的熱資料被淘汰,影響記憶體命中率,需要依靠後續的查詢請求慢慢恢復記憶體命中率。

如果可以使用 index nested-loop join 演算法,也就是說可以用上被驅動表上的索引,其實是沒問題的;

如果使用 block nested-loop join 演算法,掃瞄行數就會過多。尤其是在大表上的 join 操作,這樣可能要掃瞄被驅動表很多次,會占用大量的系統資源。所以這種 join 盡量不要用。

使用join buffer 時:在決定哪個表做驅動表的時候,應該是兩個表按照各自的條件過濾,過濾完成之後,計算參與 join 的各個欄位的總資料量,資料量小的那個表,就是「小表」,應該作為驅動表。

根據索引 a,定位到滿足條件的記錄,將 id 值放入 read_rnd_buffer 中 ;

將 read_rnd_buffer 中的 id 進行遞增排序;

排序後的 id 陣列,依次到主鍵 id 索引中查記錄,並作為結果返回。

採用該優化方案可以增加順序讀,減小隨機讀

如果想要穩定地使用 mrr 優化的話,需要設定set optimizer_switch=「mrr_cost_based=off」。

在mmr的基礎上,對nlj的優化

把錶 t1 的資料取出來一部分,先放到乙個臨時記憶體。這個臨時記憶體不是別人,就是 join_buffer。

將 join_buffer中的 a 進行遞增排序;

排序後的 id 陣列,依次到 a 索引中查記錄,並作為結果返回。

如果要使用 bka 優化演算法的話,你需要在執行 sql 語句之前,先設定

set optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';
一些情況下,我們可以直接在被驅動表上建索引,這時就可以直接轉成 bka 演算法了。

如果不適合建索引,我們可以考慮使用臨時表。

使用臨時表的大致思路是:

把錶 t2 中滿足條件的資料放在臨時表 tmp_t 中;

為了讓 join 使用 bka 演算法,給臨時表 tmp_t 的字段 b 加上索引;

讓表 t1 和 tmp_t 做 join 操作。

join演算法原理和優化

資料準備 t1 100行 id 主鍵 a t2 1000行 id 主鍵 a 索引 bindex nested loop join sql select from t1 straight join t2 on t1.a t2.a t1為驅動表,t2為被驅動表 執行流程 1.從表 t1 中讀入一行資料 ...

MySQL的JOIN(二) JOIN原理

nested loop join nlj 演算法 首先介紹一種基礎演算法 nlj,巢狀迴圈演算法。迴圈外層是驅動表,循壞內層是被驅動表。驅動表會驅動被驅動表進行連線操作。首先驅動表找到第一條記錄,然後從頭掃瞄被驅動表,逐一查詢與驅動表第一條記錄匹配的記錄然後連線起來形成結果表中的一條記。被驅動表查詢...

Pig對於資料傾斜Join的優化原理

pig對於資料傾斜join的優化原理 1 對資料抽樣 2 根據樣本資料,估計出某個key的所有的記錄數以及所佔的總記憶體,pig.skewedjoin.reduce.memusage 控制reduce消耗記憶體比例,再計算出某個key所需要的reduce個數,以及reduce的總數。3 將結果存乙個...