原文地址http://www.ovaistariq.net/521/understanding-innodb-clustered-indexes/#.VwcizRN95cA
某些用户可能并不知道MyISAM和InnoDB中索引的使用差异。如今,InnoDB被更广泛的使用,我们去理解InnoDb中索引的实现就是非常重要的。
首先最重要的是知道innodb使用了聚集索引(clustered index)存储数据。那么,什么是聚集索引呢?
聚集索引(Clustered Index)
一个聚集索引定义了表中数据的物理存储顺序。如何理解聚集索引呢,好比一个电话本,比如一个电话本是按照姓氏排序,并且电话号码紧跟着后面。因为聚集索引决定了表中数据的物理存储顺序,那么一个表则有且只有一个聚集索引。一个聚集索引可以包含多个列。好比一个电话本是基于名字,姓氏同时排序。
Innodb的聚集索引
Innodb的存储索引是基于B+tree,理所当然,聚集索引也是基于B+tree。与非聚集索引的区别则是,聚集索引既存储了索引,也存储了行值。当一个表有一个聚集索引,它的数据是存储在索引的叶子页(leaf pages)。因此innodb也能理解为基于索引的表。
现在让我们考虑下innodb如何决定那个索引作为聚集索引。
innodb如何选择一个聚集索引
对于innodb,主键毫无疑问是一个聚集索引。但是当一个表没有主键,或者没有一个索引,innodb会如何处理呢。请看如下规则
如果一个主键被定义了,那么这个主键就是作为聚集索引
如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引
如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键是一个6个字节的列,改列的值会随着数据的插入自增。
因此,笔者的建议是给每个表都定一个主键。如果该表没有逻辑主键,则创建一个自增的列作为主键。
你是否明白次级索引(secondary index)与主键的关系
在innodb,每个次级索引都存储的主键key。因为innodb的数据结构决定了,次级索引存储的是主键的值。次级索引的叶子节点并不存储行数据的物理地址。而是存储的该行的主键值。因此,换句话说,主键扮演了行数据的指针。
这是让我们推导另一个有趣的推论
一次级索引包含了两次查找。一次是查找次级索引自身。然后查找主键(聚集索引)
聚集索引的高级特性
聚集索引有非常显著的优点。如下
因为数据的物理存储是通过主键,通过主键的数据查找是非常快速的。比如,最快的方式查找一个雇员表中的某个雇员,则是通过该表的主键去匹配。同时,区间的查找也是非常快速。假定,一个应用频繁的查找某个区间的数据。一个聚集索引能快速的定位包含了开始数据,并且能检索相邻的行数据直到最后一个数据。因此,索引停工了区间的快速查询。
另一个优点,对于聚集索引,则是数据的排序实现。如果一个表的某个字段经常被用来排序,如果该字段在聚集索引列,则排序的时间就是查询的时间。同时,因为B-Tree同时保存了索引和数据值。因此通过聚集索引的检索会快于一个非聚集索引的检索。
这些优点是能提升实现,如果你设计你的表和查询。同时,聚集索引也有它的缺点。
聚集索引的缺点
如果一个很大的聚集索引被定义。那么所有的次级索引也会显而易见的大,因为次级索引存储了聚集索引的key。因为数据的存储方式,次级索引的查找需要两次。
聚集索引的列的值被更改后,聚集索引会对数据重排,因此主键被更改的开销是昂贵的。
插入可能比较慢,如果数据不是按照主键的顺序插入。因此我们判断插入的数据的效率决定于插入的顺序。在innodb的表中,插入行按照主键的顺序插入式是最快的方式。
理解次级索引
在innodb的次级索引的记录不存在被更新。因此,更新一个次级索引列意味着在该次级索引会先删除,然后插入新的数据。