Multi Range Read 代码路径

所谓MRR,简单的说就是当使用二级索引进行检索并且查询的列需要回表时,先根据检索到的PK值进行排序,然后再回表依次查询聚集索引,从而避免过多的随机IO。

测试示例:

创建一个简单的表:

CREATE TABLE `x1` (
`a` int(11) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `b` (`b`)
) ENGINE=InnoDB;

插入大量随机数据:

insert into x1 (b,c) select rand()*100, rand()*10000;

insert into x1 (b,c) select rand()*100, rand()*10000 from x1;

insert into x1 (b,c) select rand()*100, rand()*10000 from x1;

……

执行SQL:

root@sb1 04:42:15>set session optimizer_switch=’mrr_cost_based=off';
Query OK, 0 rows affected (0.00 sec)root@sb1 04:42:29>explain select * from x1 where b between 60 and 70 limit 10;
+—-+————-+——-+——-+—————+——+———+——+——–+———————————-+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows   | Extra                            |
+—-+————-+——-+——-+—————+——+———+——+——–+———————————-+
|  1 | SIMPLE      | x1    | range | b             | b    | 5       | NULL | 162690 | Using index condition; Using MRR |
+—-+————-+——-+——-+—————+——+———+——+——–+———————————-+
1 row in set (0.00 sec)

参考代码:MySQL5.6.16

1.优化器阶段:

JOIN::optimize

—> make_join_statistics

     —>get_quick_record_count

          —>SQL_SELECT::test_quick_select

               —>get_key_scans_params

                    —>check_quick_select

                         —>DsMrr_impl::dsmrr_info_const

                              —>handler::multi_range_read_info_const   //计算MRR的COST

2.初始化:

JOIN::exec —>do_select —> sub_select

—>join_init_read_record

     —>QUICK_RANGE_SELECT::reset

          —>ha_innobase::multi_range_read_init

               —>DsMrr_impl::dsmrr_init

                    —>DsMrr_impl::dsmrr_fill_buffer

                         multi_range_read_next

                              handler::read_range_first

                              handler::read_range_next

该步骤会读取请求range的二级索引key范围,并进行快速排序,主函数DsMrr_impl::dsmrr_fill_buffer

 

3.读取聚集索引记录

JOIN::exec —>do_select—>sub_select—>rr_quick—>

QUICK_RANGE_SELECT::get_next

     —>ha_innobase::multi_range_read_next

根据之前排好顺序的Primary Key值,依次读取聚集索引记录

 

4.Percona的评测:

http://www.percona.com/blog/2012/03/21/multi-range-read-mrr-in-mysql-5-6-and-mariadb-5-5/

时间: 2024-12-04 07:08:41

Multi Range Read 代码路径的相关文章

InnoDB ICP 代码路径

本文简单记录下和Index Condition Pushdown相关的代码路径 涉及的代码只包含InnoDB层 当MySQL使用索引进行数据检索时,不可用于在Innodb进行索引检索的WHERE条件,也可以下推到Innodb层,以减少回表查询的数据量 #对于innodb表,ICP只应用于二级索引 #在MySQL5.6里还不支持对分区表ICP(5.7支持) MySQL版本:5.7.5 1.创建测试表 create table t1 (a int auto_increment primary key

asp.net(C#)并非所有的代码路径都返回值

问题描述 asp.net(C#)并非所有的代码路径都返回值 public bool IsExist(string artNo1) { string artNo; List<string> list_artNo = new List<string>(); foreach (GridViewRow rows in GridView1.Rows) { artNo = rows.Cells[0].Text; list_artNo.Add(artNo); } foreach (string

radiobutton-函数不会在所有代码路径上都返回值。当使用结果时,可能会在运行时发生 null 引用异常

问题描述 函数不会在所有代码路径上都返回值.当使用结果时,可能会在运行时发生 null 引用异常 函数代码为: Function result_ss() As String If RadioButton_ss1.Checked = True Then result_ss = "1" If RadioButton_ss2.Checked = True Then result_ss = "2" End Function 求大神帮忙 解决方案 Function resul

c# 方法 foreach-C#并非所有的代码路径都返回值

问题描述 C#并非所有的代码路径都返回值 public static string aa(string a) { string str; if (str == "") { MessageBox.Show("请输入..."); return null; } else { string[] split = Regex.Split(str, ";", RegexOptions.IgnoreCase); foreach (string s in spli

方法-C# 并非所有的代码路径都返回值

问题描述 C# 并非所有的代码路径都返回值 public static string aa(string a) { if (a == "") { MessageBox.Show("请输入..."); return null; } else { string[] split = Regex.Split(a, ";", RegexOptions.IgnoreCase); foreach (string s in split) { return s;

数据结构-range tree建树代码 range search代码

问题描述 range tree建树代码 range search代码 谁能提供一份range tree建树和使用range tree进行range search的代码 或者讲解一下range tree和kd tree的区别

在线等,并非所有的代码路径都返回值问题

问题描述 for(intm=0;m<alSchedule.Count;m++){if(schedule.Equals(alSchedule[m])){returntrue;}else{returnfalse;}} alSchedule是一个存放数组的List<int[]>List用来判断数组list是否存在一个数组schedule没发现什么错误啊.... 解决方案 解决方案二:for(intm=0;m<alSchedule.Count;m++){if(schedule.Equals

错误 1 “admin_TeacherInfo.GetKmName(int)”: 并非所有的代码路径都返回值

问题描述 求教高手这个是什么原因,要怎么样改....错误代码如下:publicstringGetKmName(intnum){SqlConnectionconn=BaseClass.DBCon();conn.Open();SqlCommandcmd=newSqlCommand("selectLessonNamefromtb_LessonwhereID="+num,conn);try{stringkname=cmd.ExecuteScalar().ToString();returnkna

《编写高质量Python代码的59个有效方法》——第10条:尽量用enumerate取代range

第10条:尽量用enumerate取代range 在一系列整数上面迭代时,内置的range函数很有用. 对于字符串列表这样的序列式数据结构,可以直接在上面迭代. 当迭代列表的时候,通常还想知道当前元素在列表中的索引.例如,要按照喜好程度打印出自己爱吃的冰淇淋口味.一种办法是用range来做. 与单纯迭代f?lavor_list或是单纯使用range的代码相比,上面这段代码有些生硬.我们必须获取列表长度,并且通过下标来访问数组.这种代码不便于理解. Python提供了内置的enumerate函数,