MySQL Index--BAK和MRR演示

搭建测试环境演示BKA和MRR特性

建表语句:

## 创建测试表tb1和tb2
CREATE TABLE `tb1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_c1` (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

CREATE TABLE `tb2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_c2` (`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

## 向测试表tb1和tb2插入30万数据
## 表tb1001的id值自增
INSERT INTO tb1(c1,c2) SELECT id,id FROM tb1001;
INSERT INTO tb1(c1,c2) SELECT id,id FROM tb1001;

测试SQL:

SELECT *
FROM tb1
INNER JOIN tb2
ON tb1.c1 = tb2.C2
WHERE tb1.c1>100 AND tb1.c1<200

对应执行计划:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb1
   partitions: NULL
         type: range
possible_keys: IDX_C1
          key: IDX_C1
      key_len: 5
          ref: NULL
         rows: 99
     filtered: 100.00
        Extra: Using index condition; Using MRR
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb2
   partitions: NULL
         type: ref
possible_keys: IDX_C2
          key: IDX_C2
      key_len: 5
          ref: demodb.tb1.C1
         rows: 1
     filtered: 100.00
        Extra: Using join buffer (Batched Key Access)
2 rows in set, 1 warning (0.00 sec)

对应执行计划(JSON):

{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "258.44"
    },
    "nested_loop": [
      {
        "table": {
          "table_name": "tb1",
          "access_type": "range",
          "possible_keys": [
            "IDX_C1"
          ],
          "key": "IDX_C1",
          "used_key_parts": [
            "C1"
          ],
          "key_length": "5",
          "rows_examined_per_scan": 99,
          "rows_produced_per_join": 99,
          "filtered": "100.00",
          "index_condition": "(((`demodb`.`tb1`.`C1` > 100) and (`demodb`.`tb1`.`C1` < 200)) and (`demodb`.`tb1`.`C1` is not null))",
          "using_MRR": true,
          "cost_info": {
            "read_cost": "119.81",
            "eval_cost": "19.80",
            "prefix_cost": "139.61",
            "data_read_per_join": "1K"
          },
          "used_columns": [
            "ID",
            "C1",
            "C2"
          ]
        }
      },
      {
        "table": {
          "table_name": "tb2",
          "access_type": "ref",
          "possible_keys": [
            "IDX_C2"
          ],
          "key": "IDX_C2",
          "used_key_parts": [
            "C2"
          ],
          "key_length": "5",
          "ref": [
            "demodb.tb1.C1"
          ],
          "rows_examined_per_scan": 1,
          "rows_produced_per_join": 99,
          "filtered": "100.00",
          "using_join_buffer": "Batched Key Access",
          "cost_info": {
            "read_cost": "99.02",
            "eval_cost": "19.80",
            "prefix_cost": "258.44",
            "data_read_per_join": "1K"
          },
          "used_columns": [
            "ID",
            "C1",
            "C2"
          ]
        }
      }
    ]
  }
}

执行计划伪代码(个人理解):

c1_condition=((`demodb`.`tb1`.`C1` > 100)
    and (`demodb`.`tb1`.`C1` < 200)
    and (`demodb`.`tb1`.`C1` is not null))

tb1_mrr_buffer=new buffer(@@read_rnd_buffer_size)

tb1_search_result=[]
for each tb1_index_row(c1,id) in(range scan tb1.idx_c1 with c1_condition):
    if tb1_mrr_buffer is not full or tb1_index_row is last row:
        tb1_mrr_buffer.append(tb1_index_row(c1,id))
    else:
        ## using mrr
        tb1_mrr_buffer.sort_by(id)
        for tb1_index_row(id,c1) in tb1_mrr_buffer:
            tb1_data_row(id,c1,c2)=(search index tb1.priamry_key with id=tb1_index_row.id)
            tb1_search_result.append(tb1_data_row)
tb1_mrr_buffer.dispose()
tb1_bka_buffer=new buffer(@@join_buffer_size)
tb1_tb2_join_result=[]
for each tb1_data_row(id,c1,c2) in tb1_search_result:
    if tb1_bka_buffer is not full or tb1_data_row is last row:
        tb1_bka_buffer.append(tb1_data_row(id,c1,c2))
    else:
        ## using bka
        tb1_bka_buffer.sort_by(c1)
        for tb1_data_row(id,c1,c2) in tb1_bka_buffer:
            for tb2_index_row(c2,id) in (range scan tb2.idx_c2 where c2=tb1_data_row.c1)
                tb2_data_row(id,c1,c2)=(search index tb2.priamry_key with id=tb2_index_row.id)
                join_row=(tb1_data_row(id,c1,c2),tb2_data_row(id,c1,c2))
                tb1_tb2_join_result.append(join_row)
tb1_bka_buffer.dispose()
return tb1_tb2_join_result

PS1:MRR特性使用的buffer大小受限于参数read_rnd_buffer_size,而BKA使用的buffer大小受限于join_buffer_size

原文地址:https://www.cnblogs.com/gaogao67/p/12172876.html

时间: 2024-11-08 23:00:39

MySQL Index--BAK和MRR演示的相关文章

mysql index hint 在index不存在时的处理

关于index_hint 在mysql查询语句中可以通过指定index_hint来告诉优化器如何使用索引,详细可以参考这里 index_hint: USE {INDEX|KEY} [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list]) | IGNORE {INDEX|KEY} [FOR {JOIN|ORDER BY|GROUP BY}] (index_list) | FORCE {INDEX|KEY} [FOR {JOIN|ORDER BY|GROUP BY}

用PHP+MySQL来做分页的演示

用php做分页弄懂逻辑关系其实不难,不过我在听课的时候估计是被老师讲的那些变量里的英文单词给听懵了,因为有几个变量的名字都很像,只是换了两三个英文字母而已,有的就少几个这样的,听到一半已经不知道老师讲的这个变量代表的是什么了,写这个也只是为了复习一下,温故而知新嘛. 英文翻译:page:页   per:由,依靠 //引用数据库 下面附赠一个连接数据库的包装函数使用sql语句时用my_query()这个函数:include ./MySQLDB.php: //先设置当前选中的页码数 $pageNum

mysql 索引( mysql index )

来源:http://blog.csdn.net/luketty/article/details/5772429 索引 mysql index 索引是一种数据结构,可以是B-tree, R-tree, 或者 hash 结构.其中R-tree 常用于查询比较接近的数据:B-trees适合用于查找某范围内的数据,可以很快的从当前数据找到下条数据:hash结构则适用于随机访问的场合,查找每条数据的时间几乎相同.显然,若要查找某个时间段的数据,用B-tree结构要比hash结构快好多.         优

MySQL Index详解

FROM:http://blog.csdn.net/tianmo2010/article/details/7930482 ①MySQL Index 一.SHOW INDEX会返回以下字段 1.Table 表的名称. 2. Non_unique 如果索引不能包括重复词,则为0,如果可以则为1. 3. Key_name 索引的名称 4. Seq_in_index 索引中的列序列号,从1开始. 5. Column_name 列名称. 6. Collation 列以什么方式存储在索引中.在MySQL中,

MySQL Index Condition Pushdown(ICP)优化

Index Condition Pushdown(ICP)索引条件下推优化适用于mysql在table中通过index检索数据行,没有ICP,存储引擎层遍历索引来定位基表(base table)上的数据行并且把它们返回给server层,由server层来计算过滤where语句.使用ICP,并且where语句的部分筛选条件可以通过index来检测,则mysql server层会讲部分where 条件下推给存储引擎层.存储引擎通过使用index条目来评估下推的index condition,并且仅仅

MySQL之MHA+keepalived方案演示(五)

接着上篇博文MySQL之MHA+keepalived方案演示(四)中的MySQL的故障切换,当前主库变为了192.168.2.129机器,同时129机器上的keepalived服务被开启.然而192.168.2.128原来的主库被挂掉了,运行的keepalived也被停止了.重新启动192.168.2.128机器上的mysql,添加192.168.2.128机器上的mysql作为192.168.2.129新主库的slave从库. 查看 192.168.2.130 机器上的故障切换日志: grep

学习MYSQL之ICP、MRR、BKA

Index Condition Pushdown(ICP) Index Condition Pushdown (ICP)是MySQL使用索引从表中检索行数据的一种优化方式. ICP原理 禁用ICP,存储引擎会通过遍历索引定位基表中的行,然后返回给MySQL Server层,再去为这些数据行进行WHERE后的条件的过滤. 开启ICP,如果部分WHERE条件能使用索引中的字段,MySQL Server 会把这部分下推到存储引擎层,存储引擎通过索引过滤,把满足的行从表中读取出.ICP能减少引擎层访问基

MySQL之主从复制的配置演示

node1:192.168.139.2 主服务器 node2:192.168.139.4 从服务器 首先要在node1和node2上安装MySQL,这里不演示 然后需要对主从进行如下配置: master: 启用二进制日志 log_bin = master-bin  log_bin_index = master-bin.index 选一个唯一的服务器id server_id = {0-2^32-1} 创建具有复制权限的用户,专门用来复制 replication slave 具有从主server上复

MySQL系列详解七:MySQL实现双主架构演示-技术流ken

前言 在企业中,数据库高可用一直是企业的重中之重,中小企业很多都是使用mysql主从方案,一主多从,读写分离等,但是单主存在单点故障,从库切换成主库需要作改动.因此,如果是双主或者多主,就会增加mysql入口,增加高可用.不过多主需要考虑自增长ID问题,这个需要特别设置配置文件,比如双主,可以使用奇偶,总之,主之间设置自增长ID相互不冲突就能完美解决自增长ID冲突问题. MySQL双主(主主)架构方案思路是 1.两台mysql都可读写,互为主备,默认只使用一台(masterA)负责数据的写入,另