日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

《MySQL——join语句优化tips》

發布時間:2023/12/1 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《MySQL——join语句优化tips》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • 要不要用join
    • Join驅動表選擇
    • Multi-Range Read優化
    • Batched Key Access (BKA)對NLJ進行優化
    • BNL算法性能問題
    • BNL轉BKA

要不要用join

1、如果使用的是Index Nested-Loop Join算法,即可以用上被驅動表的索引,可以用

2、如果使用的是Block Nested-Loop Join算法。掃描行數過多,尤其是大表join會導致掃描多次被驅動表,會占用大量系統資源,這種Join盡量不要用

Join驅動表選擇

1、如果是Index Nested-Loop Join算法,使用小表做驅動表

2、如果是Block Nested-Loop Join算法,在 join_buffer_size 足夠大,大表小表一樣,當 join_buffer_size 不夠大時,選擇小表做驅動表

注意,在決定哪個表做驅動表時,應該是兩個表按照各自條件過濾完成之后,計算參與join的各個字段的總數據量,數據量小的表,那就是小表。

Multi-Range Read優化

若有這樣查詢語句:

select * from t1 where a>=1 and a<=100;

a值是遞增的,但是回表后的id并非如此,而是隨機的,會帶來性能損失。

大多數數據按照主鍵遞增順序插入得到,所以我們可以認為如果按照主鍵的遞增順序查找的話,對磁盤的讀比較接近順序讀,從而可以提升讀性能。

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

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

3、排序后的id數組,依次到主鍵id索引中查找記錄,并作為結果返回

總的來說就是:**先將索引數據緩存,查到id之后,排序之后再回表 **

用法:

設置:

set optimizer_switch="mrr_cost_based=off

現在的優化器在判斷消耗時,更傾向于不使用MRR,所以需要設置為off后,就會固定使用MRR

Batched Key Access (BKA)對NLJ進行優化

Index Nested-Loop Join執行邏輯是:從驅動表t1,一行行取出a值,再到驅動表t2去做join。對于表t2來說,每次都是匹配一個值,MMR優勢用不上。

既然這樣,將表t1的數據取出來一部分,先放到一個臨時內存里:join_buffer.

然后在此基礎上復用MRR即可。

使用方法:

set optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';

BNL算法性能問題

之前提到過InnoDB的LRU優化:第一次從磁盤讀入內存的數據頁,會先放到old區域,如果1s后這個數據頁不再被訪問,就不會移動到LRU鏈表頭部,這樣對Buffer Pool命中率影響就不大了。

如果使用了BNL的join語句,多次掃描一個冷表,并且這個語句執行時間超過1s,就會在再次掃描冷表時,把冷表的數據頁移動到LRU鏈表頭部。

如果冷表數據很大, 會一直占據old區,正常頁無法進入,無法更新young區
tips: 冷表,指表中數據還沒有加載到bufferpool中,需要先從盤里讀出來的表
又因為優化機制,一個正常訪問的數據頁要進入young區域,需要隔1s再次被訪問到。由于join’語句在循環都磁盤和淘汰內存頁,進入old區域的數據頁很可能在1s之內就被淘汰了。

大表join后對于Buffer Pool的影響是持續性的,需要依靠后續的查詢請求慢慢恢復內存命中率。

總結,BNL對于系統的影響:

1、可能多次掃描被驅動表,占用磁盤IO資源

2、判斷join條件執行M * N次,占用CPU資源

3、可能導致Buffer Pool的熱數據被淘汰,影響內存命中率

所以我們需要優化BNL,通過給驅動表的join字段加索引的方式,將BNL轉換為BKA

BNL轉BKA

對于一些不常執行大表join的sql,不在被驅動表上創建索引的情況,可以創建一個臨時表 create templete table在這個臨時表上創建索引,然后讓驅動表與臨時表做join操作。 為什么不在被驅動表上創建索引,是因為這塊sql功能不常用,創建索引浪費空間,并且可能觸發這塊的join sql 也不經常調用。

創建臨時表以及join語句示例如下:

create temporary table temp_t(id int primary key, a int, b int, index(b))engine=innodb; insert into temp_t select * from t2 where b>=1 and b<=2000; select * from t1 join temp_t on (t1.b=temp_t.b);

總結

以上是生活随笔為你收集整理的《MySQL——join语句优化tips》的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。