MySQL MRR介紹

這個文章的原始出處找不到了。html


什麼是MRR?mysql

MRR:multi range read。很差解釋,先來看個例子:sql

select * from tb where key_column = x緩存

 

在沒有MRR的狀況下,它是這樣獲得結果的:ide

1.  select key_column, pk_column from tb where key_column=x order by key_column   ---> 假設這個結果集是t性能

2.  for each row in t ;   select non_key_column from tb where pk_column = pk_column_value。(在Oracle裏第2步叫回表?)優化

在有MRR的狀況下,它是這樣執行的:spa

1.  select key_column, pk_column from tb where key_column = x  order by key_column ---> 假設這個結果集是thtm

2.  將結果集t放在buffer裏面(直到buffer滿了),而後對結果集t按照pk_column排序      ---> 假設排序好的結果集是t_sort排序

3.  select non_key_column fromtb where pk_column in (select pk_column from t_sort)

 

二者的區別主要是兩點:

1. 沒有MRR的狀況下,隨機IO增長,由於從二級索引裏面獲得的索引元組是有序,可是他們在主鍵索引裏面倒是無序的,因此每次去主鍵索引裏面獲得non_key_column的時候都是隨機IO。(若是索引覆蓋,那也就不必利用MRR的特性了,直接從索引裏面獲得全部數據)

2. 沒有MRR的狀況下,訪問主鍵索引的次數也會增長。沒有MRR的狀況下,二級索引裏面獲得多少行,那麼就要去訪問多少次主鍵索引(也不能徹底這樣說,由於MySQL實現了BNL),而有了MRR的時候,次數就大約減小爲以前次數t/buffer_size。

 因此說MRR主要解決的就是這兩個問題。



此外,MRR還能夠將某些範圍查詢,拆分爲鍵值對,以此來進行批量的數據查詢。這樣作的好處是能夠在拆分過程當中,直接過濾一些不符合查詢條件的數據。

如:

官方文檔:https://dev.mysql.com/doc/refman/5.7/en/mrr-optimization.html

> SELECT * FROM t WHERE key_part1 >=1000 AND key_part1 < 2000 AND key_part2 = 1000;

表t有(key_part1,key_part2)的聯合索引,所以索引根據key_part1,key_part2的位置關係進行排序。若沒有MRR,此時查詢類型爲Range,SQL優化器會先將key_part1大於1000且小於2000的數據都取出來,即使key_part2不等於1000。取出後再根據key_part2的條件進行過濾。這會致使無用的數據被取出。


若是啓用MRR優化器會使性能有巨大的提高,優化器會先將查詢條件拆分爲(1000,1000),(1001,1000),(1002,1000)....(1999,1000) 最後再根據這些拆分出的條件進行數據的查詢。



是否啓用MRR優化,能夠經過參數optimizer_switch中的flag來控制。當MRR爲on時,表示啓用MRR優化。mrr_cost_based表示是否經過costbased的方式來選擇是否啓用mrr。若設置mrr=on,mrr_cost_based=off,則老是啓用MRR優化。以下:

> SET GLOBAL optimizer_switch='mrr=on,mrr_cost_based=off';


參數read_rnd_buffer_size用來控制鍵值的緩衝區大小。當大於該值時,則執行器對已經緩存的數據根據RowID進行排序,並經過RowID來取得行數據,該值默認是256KB

>show VARIABLES like 'read_rnd_buffer_size';

+----------------------+---------+

| Variable_name        |   Value |

|----------------------+---------|

| read_rnd_buffer_size |  262144 |

+----------------------+---------+

相關文章
相關標籤/搜索