InnoDB存储引擎支持两种常见的索引:B+树和哈希。

B+树

B+树是从一个Balance Binary树(平衡二叉树)发展而来的,但不是一个平衡二叉树,B+树的索引只能找到被查找数据行所在的页。然后数据库通过把页读入内存,再在内存中进行查找。

平衡二叉树:左子树的值总是小于根的值,右子树的值总是大于根的键值,

二分查找法:logn

平衡二叉树对于查找的性能是比较高的,但是不是最高的,只是接近最高的性能。平衡二叉树多用于内存结构对象中,因此维护他的开销相对较小。

为什么使用B+树呢?

虽然二叉查找树和平衡二叉树都能够实现较快的数据查找,但是,由于数据库的内容是存在于磁盘上,而磁盘IO与内存IO相比,比内存IO慢了105~106倍,为了减少磁盘IO,提高检索速度,因而才用了B+树这种数据结构。换言之,B+树就是为磁盘或其他直接存取辅助设备而设计的一种多路查找树,是多叉树。

mysql b+树源码 b树 b+树 mysql_mysql索引


从上面可以看出,所有记录的节点都在页节点中,并且是顺序存放的,如果我们从最左边的节点开始遍历,可以得到的所有键值的顺序是:1、2、3、4、5、6、7。

在B+树中,所有记录节点都是按照键值的大小顺序存放在同一层的叶节点中,各个叶子节点通过指针进行连接。由于一个节点中存放了多条的数据,那么检索的时候,进行的磁盘IO次数将会少掉很多。

在B+树插入的时候,为了保持平衡,对于新插入的键值可能需要做大量的拆分页操作,而B+树主要用于磁盘,因此页的拆分意味着磁盘操作,因此应该在可能的情况下尽量减少页的拆分。因此,B+树提供了旋转的功能。至于旋转和删除等内容,过于复杂,这篇笔记先不做记录。只是了解使用B+树的原因以及B+树的特性。

InnoDB存储引擎使用聚集索引,实际的数据行和相关键值保存在一起,因此在InnoDB中要使用索引访问数据始终需要两次查找。因为索引叶子节点中存储的不是行的物理位置,而是主键的值

这是与MyISAM引擎的区别:InnoDB的数据文件本身就是索引文件,MYISAM中的索引文件和数据文件是分离的,索引文件仅仅保存数据记录的地址。InnoDB中表数据文件本身就是B+tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。InnoDB表数据文件本身就是一个主索引。

mysql b+树源码 b树 b+树 mysql_数据_02


聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

辅助索引搜索的整个查找过程:二次索引–>主键–>数据的叶子–>通过数据叶子节点中 的page directory找到数据行

因此,过程为:将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用”where id = 13”这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。

可以看出,叶节点包含了完整的数据记录,这种索引叫聚集索引。InnoDB的数据文件本身要按照主键聚集,所以InnoDB要求表必须有主键。MYISAM可以没有。

每一张InnoDB的表都会有一个主键作为索引,如果没有显示指定的话,InnoDB引擎会指派一个unique的列作为主键,如果没有unique的字段的时候,会自动的生成一个隐含的列作为主键。
这也是我们在数据库设计的时候要有一个与业务逻辑无关的auto_increment的自增主键的原因,主键索引也不要过长,否则会使辅助索引相应的变大。

聚集索引的存储是逻辑上连续的。页通过双向链表链接,按照主键的顺序排列,每个页中的记录也是通过双向链表进行维护的,物理存储上可以同样不按照主键存储。

目前我们的MySQL对于索引的添加和删除操作,都是需要创建一个新表,把原来表中的数据导入,再删除原表,将新表命名为原表,其实就是一整个都要被替换,如果一张表中数据太多的话,后期添加删除索引需要花费很长时间,因而索引一定要提前设计好。

MyISAM

mysql b+树源码 b树 b+树 mysql_mysql b+树源码_03

可以看出MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复
MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。

MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分。

MySQL的优化主要分为结构优化(Scheme optimization)和查询优化(Query optimization)
这里我们不做具体介绍。

MySQL索引:http://blog.jobbole.com/24006/