mysql 關於ICP MRR BKA等特性

2022-07-04 06:06:11 字數 4297 閱讀 8651

index condition pushdown (icp)是mysql使用索引從表中檢索行資料的一種優化方式,從mysql5.6開始支援,mysql5.6之前,儲存引擎會通過遍歷索引定位基表中的行,然後返回給server層,再去為這些資料行進行where後的條件的過濾。mysql 5.6之後支援icp後,如果where條件可以使用索引,mysql 會把這部分過濾操作放到儲存引擎層,儲存引擎通過索引過濾,把滿足的行從表中讀取出。icp能減少引擎層訪問基表的次數和 server層訪問儲存引擎的次數。

輔助索引index (a, b, c)

select * from peoplewhere a='12345' and b like '%xx%'and c like '%yy%';

若不使用icp:則是通過二級索引中a的值去基表取出所有a='12345'的資料,然後server層再對b like '%xx%'and c like '%yy%' 進行過濾

mrr 的全稱是 multi-range read optimization,是優化器將隨機 io 轉化為順序 io 以降低查詢過程中 io 開銷的一種手段,這對io-bound型別的sql語句效能帶來極大的提公升,適用於range ref eq_ref型別的查詢

mrr優化的幾個好處

使資料訪問有隨機變為順序,查詢輔助索引是,首先把查詢結果按照主鍵進行排序,按照主鍵的順序進行書籤查詢

減少緩衝池中頁被替換的次數

批量處理對鍵值的操作

在沒有使用mrr特性時

第一步 先根據where條件中的輔助索引獲取輔助索引與主鍵的集合,結果集為rest

select key_column, pk_column from tb where key_column=x order by key_column

第二步 通過第一步獲取的主鍵來獲取對應的值

for each pk_column value in rest do:

select non_key_column from tb where pk_column=val

使用mrr特性時

第一步 先根據where條件中的輔助索引獲取輔助索引與主鍵的集合,結果集為rest

select key_column, pk_column from tb where key_column = x order by key_column

第二步 將結果集rest放在buffer裡面(read_rnd_buffer_size 大小直到buffer滿了),然後對結果集rest按照pk_column排序,得到結果集是rest_sort

第三步 利用已經排序過的結果集,訪問表中的資料,此時是順序io.

select non_key_column fromtb where pk_column in (rest_sort)

在不使用 mrr 時,優化器需要根據二級索引返回的記錄來進行「回表」,這個過程一般會有較多的隨機io, 使用mrr時,sql語句的執行過程是這樣的:

通過上述過程,優化器將二級索引隨機的 io 進行排序,轉化為主鍵的有序排列,從而實現了隨機 io 到順序 io 的轉化,提公升效能

此外mrr還可以將某些範圍查詢,拆分為鍵值對,來進行批量的資料查詢,如下:

select * from t where key_part1 >= 1000 and key_part1 

< 2000and key_part2 = 10000;

表t上有二級索引(key_part1, key_part2),索引根據key_part1,key_part2的順序排序。

若不使用mrr:此時查詢的型別為range,sql優化器會先將key_part1大於1000小於2000的資料取出,即使key_part2不等於10000,帶取出之後再進行過濾,會導致很多無用的資料被取出

若使用mrr:如果索引中key_part2不為10000的元組越多,最終mrr的效果越好。優化器會將查詢條件拆分為(1000,1000),(1001,1000),... (1999,1000)最終會根據這些條件進行過濾

相關引數

當mrr=on,mrr_cost_based=on,則表示cost base的方式還選擇啟用mrr優化,當發現優化後的代價過高時就會不使用該項優化

當mrr=on,mrr_cost_based=off,則表示總是開啟mrr優化

set  @@optimizer_switch='mrr=on,mrr_cost_based=on';

引數read_rnd_buffer_size 用來控制鍵值緩衝區的大小。二級索引掃瞄到檔案的末尾或者緩衝區已滿,則使用快速排序對緩衝區中的內容按照主鍵進行排序

batched key access (bka)  提高表join效能的演算法。當被join的表能夠使用索引時,就先排好順序,然後再去檢索被join的表,聽起來和mrr類似,實際上mrr也可以想象成二級索引和 primary key的join

如果被join的表上沒有索引,則使用老版本的bnl策略(block nested-loop)

bka原理

對於多表join語句,當mysql使用索引訪問第二個join表的時候,使用乙個join buffer來收集第乙個操作物件生成的相關列值。bka構建好key後,批量傳給引擎層做索引查詢。key是通過mrr介面提交給引擎的(mrr目的是較為順序)mrr使得查詢更有效率。 

大致的過程如下:

bnl和bka都是批量的提交一部分行給被join的表,從而減少訪問的次數,那麼它們有什麼區別呢?

bka和bnl標識

using join buffer (batched key access)和using join buffer (block nested loop)

相關引數

bak使用了mrr,要想使用bak必須開啟mrr功能,而mrr基於mrr_cost_based的成本估算並不能保證總是使用mrr,官方推薦設定mrr_cost_based=off來總是開啟mrr功能。開啟bak功能(bak預設off):

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

bka使用join buffer size來確定buffer的大小,buffer越大,訪問被join的表/內部表就越順序。

set optimizer_switch=』block_nested_loop』

支援inner join, outer join, semi-join operations,including nested outer joins

bka主要適用於join的表上有索引可利用,無索引只能使用bnl

icp(index condition pushdown

index condition pushdown是用索引去表裡取資料的一種優化,減少了引擎層訪問基表的次數和server層訪問儲存引擎的次數,在引擎層就能夠過濾掉大量的資料,減少io次數,提高查詢語句效能

mrr(multi-range read

是基於輔助/第二索引的查詢,減少隨機io,並且將隨機io轉化為順序io,提高查詢效率。

nested loop join演算法

將驅動表/外部表的結果集作為迴圈基礎資料,然後迴圈該結果集,每次獲取一條資料作為下乙個表的過濾條件查詢資料,然後合併結果,獲取結果集返回給客戶端。nested-loop一次只將一行傳入內層迴圈, 所以外層迴圈(的結果集)有多少行, 記憶體迴圈便要執行多少次,效率非常差。

block nested-loop join演算法

將外層迴圈的行/結果集存入join buffer, 內層迴圈的每一行與整個buffer中的記錄做比較,從而減少內層迴圈的次數。主要用於當被join的表上無索引。

batched key access演算法

當被join的表能夠使用索引時,就先好順序,然後再去檢索被join的表。對這些行按照索引字段進行排序,因此減少了隨機io。如果被join的表上沒有索引,則使用老版本的bnl策略(block nested-loop)。

參考:

關於mysql查詢 關於MYSQL 查詢

你想要的是這種效果嗎?建立表city cost create table city cost id int primary key auto increment,cost time date,city varchar 20 money int auto increment 1 插入資料 insert...

關於mysql索引 關於mysql的索引

我們先來了解mysql索引的概念 索引是一種特殊的檔案,他們包含著對資料表裡所有記錄的引用指標。更通俗地說,資料庫索引好比是是一本書前面的目錄,能加快資料庫的查詢速度,我們有了相應的索引後,資料庫會直接在索引中查詢符合條件的選項。索引分為聚簇索引和非聚簇索引兩種,聚簇索引是按照資料存放的物理位置為順...

mysql關於日期 關於mysql日期的一些例子

mysql中的月份計算 減少乙個月,比如 原來的subtime 2006 10 22 12 22 22 減少後變成 2006 9 22 12 22 22 update message set subtime date sub subtime,interval 1 month 增加乙個月 update...