MySQL5.6 Internals--隐藏的索引列_MySQL

php中文网
发布: 2016-06-01 13:36:29
原创
1317人浏览过

bitsCN.com

MySQL5.6 Internals-隐藏的索引列

Louis Hust

 

0  前言

今天本来想跟踪mysql5.6中的新特性index merge,结果在跟踪的过程中,发现了一个问题,即innodb的二级索引中 可能会包含主索引,当然这里的包含并不是说二级索引的row里面会有pk的记录,这一点是一直存在的,这里的包含 是指,二级索引也会包含主索引进行排序。

 

1  现场重现

 

1.1  初始化数据

mysql> show create table index_merge/G*************************** 1. row ***************************       Table: index_mergeCreate Table: CREATE TABLE `index_merge` (  `c1` int(11) NOT NULL AUTO_INCREMENT,  `c2` int(11) DEFAULT NULL,  `c3` varchar(100) DEFAULT NULL,  PRIMARY KEY (`c1`),  KEY `c2` (`c2`)) ENGINE=InnoDB AUTO_INCREMENT=10002 DEFAULT CHARSET=latin11 row in set (0.00 sec)mysql> show create procedure fill_index_merge/G*************************** 1. row ***************************           Procedure: fill_index_merge            sql_mode: NO_ENGINE_SUBSTITUTION    Create Procedure: CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `fill_index_merge`(c1_cnt int, c2_cnt int)begindeclare i,j int default 1;repeat   repeat      insert into index_merge(c2,c3) values(j, repeat('a', 64));      set j = j+1;      until j > c2_cnt   end repeat;set i = i + 1;set j = 1;until i > c1_cntend repeat;endcharacter_set_client: utf8collation_connection: utf8_general_ci  Database Collation: latin1_swedish_ci1 row in set (0.00 sec)mysql> call fill_index_merge(100, 100);
登录后复制
 

1.2  查看计划

mysql> explain select * from index_merge where c1 < 100 and c2 = 50/G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: index_merge         type: rangepossible_keys: PRIMARY,c2          key: c2      key_len: 9          ref: NULL         rows: 1        Extra: Using index condition1 row in set (0.00 sec)
登录后复制

可以看到,计划中竟然是range的查询,我的第一直觉应该是ref const的查询,但是确实是range,使用c2的range, 但是c2的key_len竟然是9,我去,各种疑惑啊,于是跟踪计划生成,发现key有两个(PRIMARY, c2),但是c2的index上的列确有两列,(c2,c1)。 瞬间凌乱了,竟然隐式的修改我的index,还把用户蒙在鼓里。

 

2  原因分析

由上面的分析,可以知道c2的index在生成时,其实被MySQL隐式修改为(c2,c1)的index了,那我们就看下代码吧。

 

一开始我以为这些修改是在创建表的时候就隐式的修改了,我又错了,木有,看遍了mysql_create_frm()都没找到哪里修改了, frm文件还是那个frm文件。

 

OK,不是创建的时候修改,那只能是加载frm时候修改了,也就是内存的修改。看看数据字典的加载函数open_binary_frm(),bingo, 5.6相比5.5确实做了修改,重点代码如下:

 
open_binary_frm(){  ...  use_extended_sk= (legacy_db_type == DB_TYPE_INNODB);  ...  for (i=0 ; i < keys ; i++, keyinfo++)  {    ...    for (j=keyinfo->user_defined_key_parts ; j-- ; key_part++)    {      ...      /*      Add PK parts if engine supports PK extension for secondary keys.      Atm it works for Innodb only. Here we add unique first key parts      to the end of secondary key parts array and increase actual number      of key parts. Note that primary key is always first if exists.      Later if there is no PK in the table then number of actual keys parts      is set to user defined key parts.      */      keyinfo->actual_key_parts= keyinfo->user_defined_key_parts;      keyinfo->actual_flags= keyinfo->flags;      if (use_extended_sk && i && !(keyinfo->flags & HA_NOSAME))      {        add_pk_parts_to_sk(keyinfo, share->key_info,        &key_part, &rec_per_key);      }      share->key_parts+= keyinfo->hidden_key_parts;    }    ...  }  ...}
登录后复制
 

重点来了,首先只有InnoDB引擎才支持隐式修改second index,然后是通过add_pk_parts_to_sk()函数将pk的列 加入到second index中,当然加入过程中有些限制,如对key中可列数和key的长度的限制。

AppStruct
AppStruct

无代码应用开发平台

AppStruct 132
查看详情 AppStruct
 

3  总结

InnoDB引擎原本的二级索引中的记录就会包含pk的列,之前只是为了通过二级索引去定位主索引,也就时pk和second key之间数据 的一一映射,并没有别的用途,现在增加了在sk中对pk的排序,可以说是在没有增加存储开销的情况下,使得记录有序性更强,也就是 更加有利于最优计划的生成。当然代价可能就是插入时候key compare的时间会稍微变长。

 

总的来说,InnoDB在不断完善,Oracle也可以说是功不可没吧,虽然我个人很讨厌Oracle现在把MySQL搞的没什么活力了,很多东西不再那么open了, 比如mysql-test的test case,bug系统等,希望Oracle能把MySQL做的更好吧。

 




File translated fromTEXby TTH,version 4.03.
On 27 Jan 2013, 16:51.

bitsCN.com
最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号