热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

MySQL5.6Internals--隐藏的索引列
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 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的长度的限制。

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
推荐阅读
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 在数据分析工作中,我们通常会遇到这样的问题,一个业务部门由若干业务组构成,需要筛选出每个业务组里业绩前N名的业务员。这其实是一个分组排序的 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • Python字典推导式及循环列表生成字典方法
    本文介绍了Python中使用字典推导式和循环列表生成字典的方法,包括通过循环列表生成相应的字典,并给出了执行结果。详细讲解了代码实现过程。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 数据库(外键及其约束理解)(https:www.cnblogs.comchenxiaoheip6909318.html)My ... [详细]
author-avatar
Xl小飞2502901391
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有